很久没写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. windows CE 6.0编译报BLDDEMO: There were errors building MY283错误解决办法

    今天开始正式进入windows ce程序开发. 第一次编译windows ce6.0的系统,25分钟编译后报:BLDDEMO: There were errors building MY283 错误. ...

  2. python学习笔记1

    python3.3使用urllib2报错 no module named urllib2,原因是python3中将urllib2换成了request. 所以要使用import urllib.reque ...

  3. vimium

    安装在chrome上的一个插件,可以实现chrome无鼠标无键盘操作. 事实上vimium就是提供了一系列的快捷键列表,所以只要熟悉了这些快捷键就可以方便使用了. 要查看快捷键列表,打开chrome, ...

  4. 监听文本框输入开发仿新浪微博限制输入字数的textarea插件

    监听文本框输入 Firefox.Chrome.IE9,IE10 均支持 oninput 事件,此外所有版本的 IE 均支持 onpropertychange 事件. oninput 事件在用户输入.退 ...

  5. 【Longest Common Prefix】cpp

    题目: Write a function to find the longest common prefix string amongst an array of strings. 代码: class ...

  6. GitHub教程--上传项目四步法 GitBash命令行下使用方法

    之前就用过GitHub,感觉用GitHub托管自己的代码非常不错.可是之前用的都是窗口化的TortoiseGit,省了很多命令行的操作,但是个人非常喜欢使用命令行,于是,今天就试着用了用GitBash ...

  7. hadoop学习日志

    Hadoop思想之源:Google 面对的数据和计算难题 ——大量的网页怎么存储 ——搜索算法 带给我们的关键技术和思想 ——GFS ——Map-Reduce ——Bigtable Hadoop创始人 ...

  8. SQL-AdventureWorks样例数据库

    1. 下载样例数据库文件 输入网址:http://www.codeplex.com/ , 搜索:microsoft sql server product samples 下载对应数据库的Adventu ...

  9. 【Java】Eclipse导出jar包与javadoc

    1.导出jar包 2.导出javadoc 3.jar包添加javadoc 4.出错解决 参考资料: http://www.cnblogs.com/cyh123/p/3345889.html http: ...

  10. 【BZOJ】【2661】【Beijing WC2012】连连看

    网络流/费用流/二分图最大权匹配 拆点费用流求最大权匹配……为什么我拿zyf和Hzwer的代码也交不过去……WA了那么多次……so sad 求路过的神牛指导啊>_<万分感谢 //BZOJ ...