实现进阶的C/S通信

为了能准确,精准的传递信息,我们在服务器和客户端互相发消息的基础上,需要进行细化分类。

服务器需要能识别客户端传来的是什么请求,也就是要区分是登录消息,是注册消息,还是聊天消息。那么在客户端,简单的直接发送就满足不了这些要求,需要像"打暗号"一样,先告诉服务端我发送的消息是哪一类的,在发送消息主体

至于分类,要先对服务端和客户端进行统一要求,确保发送和收到的"暗号"是同一个,那么就先创建一个类,来存储对应的暗号,代码如下

java 复制代码
public class MessageType {
    public static final byte LOGIN = 1;  //登录
    public static final byte REGISTER = 2; //注册
    public static final byte PRIVATE = 3;  //私聊
    public static final byte GROUP = 4;   //广播
    public static final byte CHAT = 5;
    public static final byte YES = 6;
    public static final byte NO = 7;
}

这样,将这个类分别放在服务端和客户端中,统一口令

第二,服务端和客户端不是一对一的反应,一个服务端要同时接受多个客户端的请求,那么就要用到多线程。

服务端创建ServerSocket,用死循环等待每一个客户端的接入。在循环中,用accept阻塞操作,对每一个接入的用户创建一个线程。为了在线程中能找到对应的用户,在创建线程之前,就要对每个用户进行ID化,根据登录或注册的用户名和用户的Socket,创建一个Map,以键值对的形式存储用户接入的信息,以便后续的"广播"和"对话"。代码展示

java 复制代码
    //用户账号存储数组
    public List<User> userList = new ArrayList();

    public Server(){
        //初始化注册账号
        for(int i=1;i<=5;i++){
            userList.add(new User(i+"1",i+"1"));
        }
    }

    public void ServerStart() throws IOException {
        ServerSocket serverSocket = new ServerSocket(19989);
        System.out.println("服务器启动");

        Map<Integer,Socket> map = new HashMap();
        int userID=1;

        while (true) {
            Socket socket=serverSocket.accept();
            map.put(userID,socket);
            ServerThread serverThread=new ServerThread(socket,map,
                    userID++,userList);
            new Thread (serverThread).start();
        }
    }

第三,处理传来的消息。为了能实时监听用户的消息,对每一个线程也需要进行死循环,并用read方法阻塞。前文提到的先传递消息类型,后传递消息主体,也就是需要进行两次接收,先接收消息类型,通过switch case的分类,再在对应的类中处理消息。

例如,我再客户端进行登录操作,那么我就需要先发送一个Message.LOGIN的消息给服务器,在发送我的账号密码给服务器,在服务器端进行账号密码的拆解,进行判断,返回登录成功或者失败的消息返回给客户端。

客户端接受到登录成功的消息,进而跳转到对应的界面,进行下一步对话。

以下是服务端代码展示

java 复制代码
 public void run(){
        while (true) {
            try {
                int head = is.read();
                String msg = readMsg();
                switch (head) {
                    case MessageType.LOGIN:
                        handleLogin(msg);
                        break;
                    case MessageType.REGISTER:

                        break;
                    case MessageType.CHAT:
                        //判断聊天类型
                        String[] msgArr = msg.split(":");
                        if (msgArr[0].equals("g")) {
                            //广播
                            for (Map.Entry<Integer, Socket> entry : map.entrySet()) {
                                Socket s = entry.getValue();
                                if (s != socket) {
                                    OutputStream os = s.getOutputStream();
                                    sendMsg(os, msgArr[1]);
                                }
                            }
                        } else {
                            int id = Integer.parseInt(msgArr[0]);
                            //通过id找到socket
                            Socket s = map.get(id);
                            OutputStream os = s.getOutputStream();
                            sendMsg(os, msgArr[1]);
                        }
                        System.out.println("client:" + msg);
                        break;

                    default:
                        System.out.println("错误文件头");
                        break;
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
相关推荐
livemetee2 分钟前
MySQL联合唯一索引(code,deleted)与逻辑删除问题
java·数据库
MacroZheng4 分钟前
Redis官方发布高颜值可视化工具,功能更是强的离谱!
java·redis·后端
wuminyu8 分钟前
纯轻量级锁体系下C2编译器锁粗化和消除机制剖析
java·linux·c语言·jvm·c++
ss27319 分钟前
AI全栈实战 | 1.4-02 Spring AOP:@Transactional 失效的 N 种场景,根因其实只有一个
java·spring·ai编程
beijixinghe33 分钟前
第15节 指针作为函数参数的工程实战用法
开发语言·c++·c++基础·c++入门·几何引擎c++
梦想平凡41 分钟前
情怀棋牌源代码焕新记录(一):全新国风UI与原版工程梳理
java·服务器·数据库·websocket·网络协议·cocos2d
SEO_juper41 分钟前
2026年用Python分析网站访问日志:看清Googlebot和AI爬虫怎么爬你的站(附完整代码)
开发语言·前端·seo·独立站·谷歌优化
ba_pi1 小时前
springAI2.0接入mcp读取mysql
java·agent·spring ai
宸津-代码粉碎机1 小时前
Java面试核心:JVM三大GC垃圾回收算法原理与生产场景落地分析
java·大数据·人工智能·python·spring
Ivanqhz1 小时前
BPE(Byte Pair Encoding) 算法
java·服务器·网络·深度学习·神经网络