网络多线程——多用户即时通信系统(9)——无异常退出系统

在这里插入图片描述

客户端

在这里插入图片描述

在客户端的 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();
            }
        }

    }
}



测试客户端无异常退出

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值