Java实现本地Socket通信(四)

这节我们实现群聊和私发的功能(本节内容较少,重要的是要有制定消息协议的想法,代码包在绑定资源里)

一、思路

由于多了区分消息类型的需求,所以需要更新消息协议

这里我确定消息协议为

复制代码
消息类型 好友名称长度 好友名称 (信息类型) 消息长度 消息内容

并规定私聊输入格式 为**++@+用户名+空格+信息,群聊默认++**

然后只需要更改客户端的发送函数send 、服务端的接收函数receive消息处理函数proClintMsg(Socket socket)

下面我们来实现它

二、代码实现

首先更改客户端的发送函数send,判断其是群聊还是私聊,私聊1 群聊2,如果是群聊就使用原代码(前面加上发送消息类型)

如果是私聊就单独写其处理逻辑

第一步先拆分传入的信息,前半段为用户名,后半段为信息,然后依次转成字节数据传出(注意先传消息类型,这个是需要自行添加的,原消息中没有)

java 复制代码
    public void send(String  message){

        //文字消息: 消息类型 好友名称长度 好友名称 信息类型 消息长度 消息内容
        //先通过@来区分是否是私聊
        char c1=message.charAt(0);

        try {
            OutputStream os=socket.getOutputStream();
            if(c1=='@'){
                //私聊
                int index=message.indexOf(" ");//找到空格的下标
                String friendName=message.substring(1,index);
                String msg=message.substring(index+1);
                System.out.println("正在发送给:"+friendName);
                //组装消息内容
//            message="1"+friendName.length()+friendName+msg.length()+msg;
                os.write(1);
                int fn=friendName.getBytes().length;
                os.write(fn);
                os.write(friendName.getBytes());
                int msglen=msg.getBytes().length;
                os.write(msglen);
                os.write(msg.getBytes());
            }else{
                os.write(2);//群聊
                byte[] msgs=message.getBytes();
                int len=msgs.length;
                os.write(len);
                os.write(msgs);
            }
            os.flush();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

其次,修改服务端中的接收receive函数

由于传入的消息协议不同,所以需要制定不同的读取方案

如下

java 复制代码
    public String receive(InputStream is){
        try {
            //读取消息类型 群聊2 私聊2=1
            int type=is.read();
            if (type==1){
                //私聊
                int idlen=is.read();
                byte[] id=new byte[idlen];
                is.read(id);
                String friendName=new String(id);
                int msglen=is.read();
                byte[] msgs=new byte[msglen];
                is.read(msgs);
                String msg=new String(msgs);
                return "1"+"#"+friendName+"#"+msg;
            }else{
                //群聊
                int len=is.read();
                byte[] msgs=new byte[len];
                is.read(msgs);
                String msg=new String(msgs);
                System.out.println("收到:"+msg);
                return "2"+"#"+" "+"#"+msg;
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

同理,在消息处理函数中,虽然消息协议相同,但是传出对象不同,所以同样需要分类判断,具体发方法如下(代码意思很明显,就不过多赘述了)

java 复制代码
public void proClintMsg(Socket socket){
        //注意:循环速度太快,导致cpu被占满,io流根本没机会运行,所以这里加一个println,让cpu空闲下来
            new Thread(()->{
                //登录
                //读取用户名
                String UserName=proLogein(socket);
                ClientUser cu=new ClientUser(UserName,socket);
                //保存ClientUser对象
                SocketList.add(cu);
                while(true) {
                    try {
                        InputStream is=cu.socket.getInputStream();
                        System.out.println("监听"+cu.socket.getPort()+"消息中:");//顺序不对?
                        String msg=receive(is);
                        //区分群聊消息还是私发消息
                        String [] datas=msg.split("#");
                        String type=datas[0];
                        String friendName=datas[1];
                        String msgs=datas[2];
                        if(type.equals("1")){
                            for(int i=0;i<SocketList.size();i++){
                                ClientUser cu1=SocketList.get(i);
                                if(cu1.account.equals(friendName)){
                                    msgs=cu.account+"说:"+msgs;
                                    send(msgs,cu1.socket.getOutputStream());
                                    break;
                                }
                            }
                        }else{
                            replyMsg(cu,msgs);
                        }
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }).start();
    }

其他没有变化

这样,群聊和私发的功能便初步实现了

相关推荐
网安蟹佬霸1 分钟前
密码学安全实战:从加密原理到哈希破解的完整攻防指南
网络·算法·安全·web安全·开源·密码学·哈希算法
AI备忘录35 分钟前
(十一)DHCP 配置命令五厂商对照:华为 华三 锐捷 迈普 思科
服务器·网络·网络协议·网络安全·华为
迪康coolmu1 小时前
企业文件外发防泄漏实践:从通道封堵到三层全链路管控
大数据·运维·网络·人工智能·安全·阿里云
星恒讯工业路由器9 小时前
新一代通信网:从“连接万物”到“智联万物”的关键跃迁
网络·物联网·智能路由器·工业路由器·工业物联网·5g-a·新一代通信网
暴力求解11 小时前
Linux网络---传输层协议TCP(二)
linux·服务器·开发语言·网络·tcp/ip
石头猫灯11 小时前
WordPress wp2shell 漏洞链完整拆解流程
网络·数据结构·安全·web安全
网安蟹佬霸11 小时前
OSINT开源情报收集实战:从信息搜集到资产测绘(2026最新万字保姆级指南)
前端·网络·安全·web安全·网络安全·开源
80s77713 小时前
动态ip和静态ip有什么区别
服务器·网络·tcp/ip
鲁邦通物联网13 小时前
出海物联网设备的全球化网络接入与合规脱敏架构:基于 Node-RED 与 C++ 零拷贝的边缘系统设计
网络·物联网·系统架构·边缘计算·边缘计算网关·5g数采·工业级边缘计算网关
星恒讯工业路由器13 小时前
家庭无线组网方式全解析:从单路由到FTTR,哪种适合你?
网络·物联网·智能路由器·路由器·家庭组网·ac+ap·mesh组网