网络编程v2--多客户端互通

一(前言)、由于一代版本仅支持客户端和服务端互通,暂时缺少客户端之间的沟通,所以在第二代版本中进行更新,二代版本中使用多实例实现多个客户端,并且支持某一客户端发的信息能被其他客户端接收,同时也能被服务端接收,下面做代码解释

二(服务端类代码解释

1.全局变量为服务端套接字和一个普通套接字数组

2.函数1(初始化函数):作用是让服务端套接字绑定特定接口,监听该接口的连接请求

3.函数2(监听链接函数):返回值为向特定接口发起连接请求的客户端套接字,可用于获取该客户端的输入输出流

4.函数3(给指定套接字发指定信息的函数):参数表有两个变量,也即想联系的套接字和字符串内容。发送函数同v1逻辑,通过获取该套接字的输出流,并输出特定内容

5.函数4(使客户端持续读取信息并且广播该信息的函数):这里用到Lambda表达式以及增强型for循环实现功能

6.函数5(主函数):包含初始化,在死循环中监听客户端发起的连接请求,并将新连接进的客户端加入sockets数组中

java 复制代码
public class Server {
    ServerSocket ss=null;
    ArrayList<Socket> sockets=new ArrayList<>();//存所有连接上来的客户端
    //初始化函数
    public void initialize(){
        try {
            ss=new ServerSocket(54321);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //监听连接
    public Socket listen(){
        try {
            return ss.accept();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //发消息给指定socket
    public void send(Socket s,String msg){

        try {
            //获取该socket的输出流
            OutputStream os=s.getOutputStream();
            byte[] data=msg.getBytes(StandardCharsets.UTF_8);
            os.write(data.length);//发字节数组长度
            os.write(data);//发消息
            os.flush();//刷新
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //收取消息
    public String receive(InputStream inputStream){
        try {
            int length=inputStream.read();
            if(length==-1)return null;
            byte[] data=new byte[length];
            inputStream.read(data);
            //返回特定格式字符串
            return new String(data,StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
    //给某个socket开独立线程,死循环收消息并且群发
    public void handeleClient(Socket client){
        new Thread(() -> {
            try {
                InputStream inputStream=client.getInputStream();
                while (true){
                    String msg=receive(inputStream);
                    if(msg==null)break;
                    System.out.println(client.getInetAddress()+":"+client.getPort()+"->"+msg);
                    for(Socket s:sockets){
                        if(s!=client){
                            send(s,msg);
                        }
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }).start();
    }
    //主函数
    public static void main(String[] args) {
        Server server=new Server();
        server.initialize();
        System.out.println("服务端启动,监听接口"+server.ss.getLocalPort());
        while (true){
            Socket client=server.listen();
            server.sockets.add(client);
            System.out.println("新连接:"+client.getInetAddress()+":"+client.getPort());
            server.handeleClient(client);
        }
    }

}

三(客户端代码解释)

1.函数一(初始化)

2.函数二(收信息函数):通过输入流的read函数实现

3.函数三(发消息函数)

4.函数四(启动一个线程,使客户端的收发信息相互独立)

5.函数五(主函数):先启动收发信息线程,再循环读取输入流的消息并且群发广播

java 复制代码
public class Client {
    Socket socket=null;
    //初始化
    public void initialize(){
     try {
         socket=new Socket("127.0.0.1",54321);
     } catch (IOException e) {
         throw new RuntimeException(e);
     }
    }
    //收信息函数
    public String receive(){
        try {
            InputStream in=socket.getInputStream();
            int length=in.read();
            byte[] data=new byte[length];
            in.read(data);
            return new String(data, StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
    //发信息函数
    public void send(String msg){
        try {
            OutputStream os=socket.getOutputStream();
            byte[] data=msg.getBytes(StandardCharsets.UTF_8);
            os.write(data.length);//发字节数组长度
            os.write(data);//发消息
            os.flush();//刷新
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //收信息线程,使客户端实现收发信息独立,能同时收发消息
    public void startreceiveThread(){
        new Thread(() -> {
            while (true){
                String msg=receive();
                if(msg==null)break;
                System.out.println("收到"+msg);
            }
        }).start();
        System.out.println("启动收信息线程");
    }

    //主函数
    public static void main(String[] args) {
        Client client=new Client();
        client.initialize();
        client.startreceiveThread();//收信息线程先启动
        Scanner scanner=new Scanner(System.in);
        while (true){
            String msg=scanner.nextLine();
            client.send(msg);
        }
    }
}

四(效果展示)

相关推荐
霸道流氓气质1 小时前
SpringBoot中基于 AES-GCM + KMS 密钥管理的数据加解密 Starter 实践
java·数据库·spring boot
Meya11272 小时前
实时采集 + 全域可视化,打造跨站点机房一体化U位管理方案
大数据·运维·人工智能
Gofarlic_OMS2 小时前
NX浮动许可调度黑名单机制,对比两款谁更合理
java·大数据·运维·开源·制造
万岳科技系统开发2 小时前
智慧医院小程序开发推动医疗服务流程全面线上化
大数据·开发语言·人工智能
一只小灿灿2 小时前
C++ 修饰符全面详解
开发语言·c++
马里马里奥-2 小时前
从零搭建AI Agent工具链的技术文章大纲
开发语言·qt
三言老师2 小时前
CentOS7.9:Redis服务器部署结构化实战教程
linux·运维·服务器·数据库
乐观的Terry2 小时前
8、发布系统-完整流水线的核心
java·spring boot·spring·spring cloud
Alexalbb2 小时前
从角色过滤到可审计授权:单体系统数据权限设计复盘与演进
java