很久没写BLOG了,之前在写Android聊天室的时候答应过要写一个客户(好友)之间的聊天demo,Android 基于Socket的聊天室已经实现了通过Socket广播形式的通信功能。

以下是我写的一个类似现在多数聊天软件的冒泡聊天APP。全部功能都是自己的想法,对于现在市面上成功的例子是怎么实现的,我还不了解。所以读者可只做参考学习,也可以分享您的案例给我。

功能

  • 一对一聊天,非聊天室
  • 好友列表
  • 好友在线,离线状态(实时更新)
  • 冒泡实时聊天窗口
  • 发送离线信息

基本原理

之前的聊天室原理:每当客户端Socket连接到该ServerSocket之后,程序将对应Socket加入clients集合中保存,并为该Socket启动一条线程,该线程负责处理该Socket所有的通信任务,当服务器线程读到客户端数据之后,程序遍历clients集合,并将该数据向clients集合中的每个Socket发送一次 

一对一的聊天:Server通过Map把Clients的Socket都储存起来,把Client用户ID作为Map的key,当A发送信息给B时,服务器搜索出B的Socket,建立他们的通信通道。

服务器Server

这次我在服务器加入了2个Socket集合,一个用来处理用户Online/Offline,另一个则专门用于处理用户之间的通信信息传递

1 static Map<String, Socket> socketMap = new HashMap<String, Socket>();
2 static Map<String, Socket> onlineMap = new HashMap<String, Socket>();

Clients 上线,下线动作,Server都会经过筛选然后通知其在线的好友,Clients收到好友的在线状态然后修改Friends List。

1 //save client's name ,online
2 //...3 getnameString = str.substring(config.PROTOCOL_KEY.length()+config.PROTOCOL_ONLINE.length());
4 Server.onlineMap.put(getnameString, s);
5 //...
6 //update online friends7 DataOutputStream onlineDOS = new DataOutputStream (Server.onlineMap.get(clientKey).getOutputStream());
8 onlineDOS.writeUTF(config.PROTOCOL_FRIENDS_START+onlineString+config.PROTOCOL_FRIENDS_END);
9 onlineDOS.flush();

关于聊天,我是通过一个自定义加密符来给每个Client做标志的,例如:Client A发出的信息,该条信息的头部带有一条服务器和客户端都会识别的特殊符号,通过字符处理,找出该条信息的用户信息;以此类推,Client A的通信对象也是用这个方法

我们找到ClientA的目标对象后,找出这个Socket通道,他们就可以一对一的对话了

1 //send msg to friend2 DataOutputStream ndos = new DataOutputStream (Server.socketMap.get(forname).getOutputStream());
3 ndos.writeUTF(fromname+date+"\n"+forchat);
4 ndos.flush();

关于离线信息,这个主要是服务器承担的功能,我是使用mySql保存数据的。Client A 向离线状态的Client B发送一条信息,Server会判断Client B是否在线,如果是离线状态,服务器则把该信息先保存在mySql里;当Client B上线时,服务器会查找它的离线信息,如果有未读信息,则会及时发送。Client B就能收到离线信息了  ( ̄ˇ ̄) 

客户端 Clients

        

关于聊天,为了能够实现同时与多个好友聊天(不同窗口线程),这里用了ContentProvider监视聊天数据的变化,使不在当前聊天窗口的Activity也能收到好友的信息拼打印。

1 //监视聊天数据的变化2 getContentResolver().registerContentObserver(DataChangeProvider.CONTENT_URI,true, cob);

那后台是怎么样接收好友发来的信息的呢?上面Server里说过,有一个SocketMap的集合,而这个集合就是记录用户的通信Socket,当有信息的时候,客户端后台的WaitMsg()会接到发来的信息并做处理。

1 private Runnable waitThread = new Runnable() {
2 public void run() {
3 System.out.println("wait running!");
4 WaitMsg();
5 }
6 };

关于Online/Offline状态,好友列表Activity ReceiveMsg()会监视Server发送的好友状态信息,及时更新好友列表ListActivity。

1 //更新好友数据库2 fanDS.updateData(reMsg,name);
3 //获取好友列表4 fansArray = fanDS.getFans();
5
6 friends = new Friends(fansArray,reMsg,name);
7 friendList = friends.getFriends();

总结

相对聊天室而言,一对一的聊天主要是对每个Client的Socket都标志记录起来,让每个通讯动作有了目标对象;Server作为信使把两者的Socket对接,使两者可以通信聊天。

这是在 TCP/IP协议下的 C/S 模式通信方式,还有UDP协议,P2P模式下的通信方式的值得再去学习。

Android 基于Socket的聊天应用(二)的更多相关文章

  1. Android 基于Socket的聊天室(一)

    Socket是TCP/IP协议上的一种通信,在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路.一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信. Client A ...

  2. socket实现聊天功能(二)

    socket实现聊天功能(二) WebSocket协议是建立在HTTP协议之上,因此创建websocket服务时需要调用http模块的createServer方法.将生成的server作为参数传入so ...

  3. java基于socket公共聊天室的实现

    项目:一个公共聊天室功能的实现,实现了登录聊天,保存聊天记录等功能. 一.实现代码 1.客户端 ChatClient.java import java.io.BufferedReader; impor ...

  4. Android基于socket的群聊程序

    在网上看了好多,但是感觉不是太简单就是只能单独聊,所以就自己写了个可以群聊的,直接上代码了 一.服务器端 这里用的MyEclipse作为服务器端 MyServerScoket.java package ...

  5. Android—基于Socket与上传图片到客户端

    最近项目中需要客户端和Socket互相传递数据时候需要相互传递图片所以做下总结以免以后忘记,也希望给大家带来帮助. 先上客户端的代码: 根据图片名称上传照相机中单个照片(此方法为自己封装) 参数所代表 ...

  6. android基于开源网络框架asychhttpclient,二次封装为通用网络请求组件

    网络请求是全部App都不可缺少的功能,假设每次开发都重写一次网络请求或者将曾经的代码拷贝到新的App中,不是非常合理,出于此目的,我希望将整个网络请求框架独立出来,与业务逻辑分隔开,这样就能够避免每次 ...

  7. Android基于XMPP Smack openfire 开发的聊天室

    Android基于XMPP Smack openfire 开发的聊天室(一)[会议服务.聊天室列表.加入] http://blog.csdn.net/lnb333666/article/details ...

  8. 基于android的Socket通信

    一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户 ...

  9. C#基于Socket的简单聊天室实践

    序:实现一个基于Socket的简易的聊天室,实现的思路如下: 程序的结构:多个客户端+一个服务端,客户端都是向服务端发送消息,然后服务端转发给所有的客户端,这样形成一个简单的聊天室功能. 实现的细节: ...

随机推荐

  1. 自己编写基于MVC的轻量级PHP框架

    做WEB开发已有三年,每次都写重复的东西, 因此,想自己写一下框架,以后开发方便.本人之前asp.NET一年开发,jsp半年,可是后来因为工作的原故换成PHP.其实很不喜欢PHP的语法.还有PHP的函 ...

  2. 解决sharepoint 2010 用户配置文件同步服务 正在启动

    用户配置文件同步服务一直显示“正在启动”,而且无法停止,如下办法可以停止这个服务: 在sharepoint power shell 中执行下面的命令: Get-spserviceinstance 获取 ...

  3. 修改ip脚本

    1.打开运行 2.输入CMD 3.在命令提示符下输入: netsh -c interface ip dump > C:\我的网络配置.txt 4.打开您在C:\ 下的"我的网络配置 . ...

  4. VS2013中如何更改主题颜色(深色)和恢复默认的窗口布局

    1.通常情况下,我们会根据个人爱好更改VS2013的主题颜色,一开始我喜欢白色,后来我偏爱深色. 依次选择:工具->选项->常规->主题->深色->确定,ok 2.我们在 ...

  5. 仿照CREATE_FUNC实现CCLayer中的返回CCScene* 的静态函数,宏包装成CREATE_SCENE(XXLayer)

    #define CREATE_SCENE(__TYPE__)\ CCScene *scene()\ { CCScene *scene=CCScene::create();\ __TYPE__ *lay ...

  6. Jquery.ajax(……)

    ajax 详细解释:http://www.cnblogs.com/mybest/archive/2011/12/13/2285730.html: 问题描述:页面发送ajax请求,服务器端返回代码总是进 ...

  7. Entity Framework公共的增删改方法

    using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.I ...

  8. Leetcode#128 Longest Consecutive Sequence

    原题地址 1. 把所有元素都塞到集合里2. 遍历所有元素,对于每个元素,如果集合里没有,就算了,如果有的话,就向左向右拓展,找到最长的连续范围,同时在每次找的时候都把找到的删掉.这样做保证了同样的连续 ...

  9. ActiveMQ主从配置

    这种方式有个问题,activemq1有消息没消费完但是突然宕机,虽然程序会自动连到activemq2.但是activemq1的消息只有等机器恢复后才会被消费. 1.启动:我这里使用的是apache-a ...

  10. HDU4542 小明系列故事——未知剩余系

    大赞的数论题: 大致思路: 对于TYPE=1的情况,认为 X 中有 X-K个约数,求最小的X,X-K>0 那么化为B+K的约数为B, 我们知道(B+K)的约数<=2*SQRT(B+K);这 ...