客户端
在客户端的 UserClientService 类中编写 logout 方法
// 1. 验证用户登录
....
// 2. 向服务器端请求在线用户列表
....
// 3. 编写方法,退出客户端,并给服务端发送一个退出系统的 Message 对象
public void logout(){
Message message = new Message();
message.setMesType(MessageType.MESSAGE_CLIENT_EXIT);
message.setSender(user.getUserId()); // 一定要指明是哪个客户端 id
// 发送 Message 对象
try {
// ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
ObjectOutputStream oos
= new ObjectOutputStream(
ManageClientConnectServerThread.getClientConnectServerThread(
user.getUserId()).getSocket().getOutputStream());
oos.writeObject(message);
System.out.println(user.getUserId() + " 退出系统...");
System.exit(0); // 结束进程
} catch (IOException e) {
e.printStackTrace();
}
}
在 QQView 中调用 logout 方法
服务端:ServerConnectClientThread 中添加客户端退出的业务逻辑
ServerConnectClientThread
package com.qqserver.service;
import com.qqcommon.Message;
import com.qqcommon.MessageType;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
/**
* @Author: Gin
* @Description: 该类的一个对象和某个客户端保持通信
* @Modified By: Gin
* @Date: Created in 14:23 2021/10/14
*/
public class ServerConnectClientThread extends Thread{
private Socket socket;
private String userId; // 连接到服务端的用户 id
public ServerConnectClientThread(Socket socket, String userId) {
this.socket = socket;
this.userId = userId;
}
@Override
public void run() {
while(true){
try {
// 服务端线程,等待读取从客户端发送过来的消息
System.out.println("客户端" + userId + "和服务端保持通信,读取数据...");
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
// 如果服务端没有发送 Message 对象,则线程在这里会阻塞
Message msg = (Message) ois.readObject();
// 根据 msg 的类型,做相应的业务处理
if(MessageType.MESSAGE_GET_ONLINE_FRIEND.equals(msg.getMesType())){
// 客户端要在线用户列表
System.out.println(msg.getSender() + " 要在线用户列表...");
String onlineUser = ManageServerConnectClientThread.getOnlineUser();
// 得到在线用户列表,需要构建一个 Message 对象,来返回给客户端
Message message = new Message();
message.setMesType(MessageType.MESSAGE_RETURN_ONLINE_FRIEND);
message.setContent(onlineUser);
message.setGetter(msg.getSender());
// 通过 Socket 对象获取对象输出流,将 Message 对象放入数据通道
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(message);
}else if(MessageType.MESSAGE_CLIENT_EXIT.equals(msg.getMesType())){
// 客户端退出
System.out.println(msg.getSender() + " 要退出...");
// 将这个客户端对应的线程从集合中删除
ManageServerConnectClientThread.removeServerConnectClientThread(userId);
// 关闭连接
socket.close();
// 退出线程
break;
}else{
System.out.println("其它类型的 Message 对象,暂不处理...");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
测试客户端无异常退出