一、概述
之前介绍了通信架构的服务器如何搭建以及客户端界面如何实现,本章着重讲解如何实现客户端消息收发。
二、原理
之前文章中所介绍的服务器模型可以接受客户端发送过来的消息(InputStream)如果想让客户端接收到消息,我们可以再服务端将消息发送给客户端,因此我们需要再服务端新建一个输出流,这就是消息收发的基本思想。
三、实现过程
1、用户列表:关于消息接收我们可以新建一个服务器,并且初始化一个哈希表用于记录连接到该服务器的用户
public class ClientMessage {
ServerSocket serverSocket;
int port = 25000;//设置消息收发服务器端口
public ClientMessage(){}
public void initServer(){
//日志信息输出
System.out.println(new TimeGetter().getTime() + "MessageSaveServer is started <- ClientMessage");
try {
serverSocket = new ServerSocket(port);
while (true) {
//新建消息接收线程
new InfoGetter(serverSocket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class InfoGetter extends Thread implements Config {
ServerSocket serverSocket;
//新建一个哈希表用于保存连接到该服务器用户的Socket对象
HashMap<String , Socket> msgServerLink = new HashMap<>();
public InfoGetter() {
}
public InfoGetter(ServerSocket serverSocket) {
this.serverSocket = serverSocket;
}
@Override
public void run() {
}
}
2、消息接收:当客户端将消息发送后,会生成一个JSON数据包并发送给服务器。服务器通过解析JSON数据包获取到收、发人的消息和内容,并将连接到该服务器的用户Socket保存起来。
public void run() {
Socket accept = null;
while (true) {
try {
//创建消息接收对象
accept = serverSocket.accept();
//创建输入流
InputStream in = accept.getInputStream();
int len = in.read();
byte [] data = new byte[len];
in.read(data);
String message = new String(data , 0 , len);
//客户端发送消息时将以JSON形式发送,因此需要解析JSON信息
JSONObject js = new JSONObject(message);
String userID = (String) js.get("userID");//发送人ID
String friendID = (String) js.get("friendID");//接收人ID
String content = (String) js.get("content");//消息内容
String sendTime = (String) js.get("sendTime");//发送时间
int msgType = (Integer) js.get("msgType");//发送消息的类型
//判断用户是否在线并保存其Socket对象
if(!msgServerLink.containsKey(userID)){
msgServerLink.put(userID , accept);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3、消息转发:当服务器转发消息时,先从解析后的JSON数据中读取收件人ID,并从哈希表中查询到收件人的Socket,并初始化该Socket的OutputStream,最后将信息进行编码转发
public void run() {
Socket accept = null;
while (true) {
try {
accept = serverSocket.accept();
InputStream in = accept.getInputStream();
int len = in.read();
byte [] data = new byte[len];
in.read(data);
String message = new String(data , 0 , len);
MessageCheck messageCheck = new MessageCheck();
messageCheck.saveMessage(message);
JSONObject js = new JSONObject(message);
String userID = (String) js.get("userID");
String friendID = (String) js.get("friendID");
String content = (String) js.get("content");
String sendTime = (String) js.get("sendTime");
int msgType = (Integer) js.get("msgType");
InfoCheck info = new InfoCheck();
String sender = info.getFriendName(friendID);
if(!msgServerLink.containsKey(userID)){
msgServerLink.put(userID , accept);
}
//信息编辑,添加发件人信息,消息发送时间以及发送的内容
String reciveMsg = sendTime + "##" + sender + "##" + content;
byte [] reciveMessage = reciveMsg.getBytes();
Socket newAccpet = msgServerLink.get(friendID);
System.out.println(newAccpet);
//初始化接收人输出流
OutputStream out = newAccpet.getOutputStream();
out.write(reciveMessage.length);
out.write(reciveMessage);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
四、运行效果
1、同时登录两个客户端
2、打开消息收发界面