Android 基于Socket的聊天应用实例(二)
作者:那瞬间 发布时间:2023-11-02 21:48:32
前言
很久没写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,另一个则专门用于处理用户之间的通信信息传递
static Map<String, Socket> socketMap = new HashMap<String, Socket>();
static Map<String, Socket> onlineMap = new HashMap<String, Socket>();
Clients 上线,下线动作,Server都会经过筛选然后通知其在线的好友,Clients收到好友的在线状态然后修改Friends List。
//save client's name ,online
//...
getnameString = str.substring(config.PROTOCOL_KEY.length()+config.PROTOCOL_ONLINE.length());
Server.onlineMap.put(getnameString, s);
//...
//update online friends
DataOutputStream onlineDOS = new DataOutputStream (Server.onlineMap.get(clientKey).getOutputStream());
onlineDOS.writeUTF(config.PROTOCOL_FRIENDS_START+onlineString+config.PROTOCOL_FRIENDS_END);
onlineDOS.flush();
关于聊天,我是通过一个自定义加密符来给每个Client做标志的,例如:Client A发出的信息,该条信息的头部带有一条服务器和客户端都会识别的特殊符号,通过字符处理,找出该条信息的用户信息;以此类推,Client A的通信对象也是用这个方法
我们找到ClientA的目标对象后,找出这个Socket通道,他们就可以一对一的对话了
//send msg to friend
DataOutputStream ndos = new DataOutputStream (Server.socketMap.get(forname).getOutputStream());
ndos.writeUTF(fromname+date+"\n"+forchat);
ndos.flush();
关于离线信息,这个主要是服务器承担的功能,我是使用mySql保存数据的。Client A 向离线状态的Client B发送一条信息,Server会判断Client B是否在线,如果是离线状态,服务器则把该信息先保存在mySql里;当Client B上线时,服务器会查找它的离线信息,如果有未读信息,则会及时发送。Client B就能收到离线信息了 ( ̄ˇ ̄)
客户端 Clients
关于聊天,为了能够实现同时与多个好友聊天(不同窗口线程),这里用了ContentProvider监视聊天数据的变化,使不在当前聊天窗口的Activity也能收到好友的信息拼打印。
//监视聊天数据的变化
getContentResolver().registerContentObserver(DataChangeProvider.CONTENT_URI,true, cob);
那后台是怎么样接收好友发来的信息的呢?上面Server里说过,有一个SocketMap的集合,而这个集合就是记录用户的通信Socket,当有信息的时候,客户端后台的WaitMsg()会接到发来的信息并做处理。
private Runnable waitThread = new Runnable() {
public void run() {
System.out.println("wait running!");
WaitMsg();
}
};
关于Online/Offline状态,好友列表Activity ReceiveMsg()会监视Server发送的好友状态信息,及时更新好友列表ListActivity。
//更新好友数据库
fanDS.updateData(reMsg,name);
//获取好友列表
fansArray = fanDS.getFans();
friends = new Friends(fansArray,reMsg,name);
friendList = friends.getFriends();
总结
相对聊天室而言,一对一的聊天主要是对每个Client的Socket都标志记录起来,让每个通讯动作有了目标对象;Server作为信使把两者的Socket对接,使两者可以通信聊天。
这是在 TCP/IP协议下的 C/S 模式通信方式,还有UDP协议,P2P模式下的通信方式的值得再去学习。
现在把代码直接放上博客园,Download:demo
来源:http://www.cnblogs.com/-run/archive/2012/04/07/2434837.html


猜你喜欢
- 这里我们只介绍springboot2.0的session时间设置Duration转换字符串方式,默认为正,负以-开头,紧接着P,(字母不区分
- 本文实例为大家分享了android自定义View实现五子棋的具体代码,供大家参考,具体内容如下先说一下吧,android的自定义View就是
- 在设置过webBrowser控件的ObjectForScripting属性后,还需要设置应用程序对com可见,不然会抛出一个异常(Objec
- 目录多开理论基础多开实现原理解析代码实现:多开包名代码实现:多用户总结多开理论基础app多开常用于做一些不合法的事情,如高羊毛,黑灰产,甚至
- DataSource在数据库应用中,客户端与数据库服务端建立的连接对象(Connection)是宝贵的资源,每次请求数据库都创建连接,使用完
- 用户关闭软件时,软件一般会给“是否确认关闭”的提示。通常,我们把它写在FormClosing 事件中,如果确定关闭,就关闭;否则把FormC
- 当你使用synchronized关键字的时候,是通过互斥器来保障线程安全以及对共享资源的同步访问。线程间也经常需要更进一步的协调
- 本文实例分析了C#队列Queue用法。分享给大家供大家参考。具体分析如下:队列(Queue)在程序设计中扮演着重要的角色,因为它可以模拟队列
- 前言继承是面向对象语法的三大特征之一。继承可以降低代码编写的冗余度,提高编程的效率。通过继承,子类获得了父类的成员变量和方法。一个子类如何继
- 本次主要分享的是3个免费的二维码接口的对接代码和测试得出的注意点及区别,有更好处理方式多多交流,相互促进进步;最近在学习JavsScript
- preHandle: 预先处理,在目标的controller方法执行之前,进行处理postHandle: 在目标的con
- 下面是一段大家都比较熟悉的代码:Handler handler = new Handler(); handler.post(myThread
- we can custom min heap or max heap by override the method compare.pack
- 本文为大家分享了C#导入导出Excel数据的具体代码,供大家参考,具体内容如 * :对于实体类对象最好新建一个并且继承原有实体类,这样可以将类
- 两种情况setState() 能在 build() 中直接调用吗?答案是能也不能。来看一段简单的代码:import 'package
- 先看下面图片:这是我在做登录页面的时候,调用系统的ProgressDialog 进行等待,可是看起来很不协调,左边的等待图片过大,右边文字过
- 某些情况下我们可能需要与Mysql或者Oracle数据库进行数据交互,有些朋友的第一反应就是直接在Android中加载驱动然后进行数据的增删
- Dart实体类格式class CategoryMo { String name; int count;CategoryMo({this.na
- 首先要安装SpeechSDK5.1 开发包和SpeechSDK5.1 Langague Pack(中英文) 语言包,不过VS2010里是自带
- 下面先看一下效果图using UnityEngine;using System.Collections;public class textM