网络编程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);
        }
    }
}

四(效果展示)

相关推荐
小羊没烦恼!5 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里5 天前
java中的继承和多态的区别
java
小羊没烦恼!5 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕5 天前
JSONObject与JSONArray封装数据格式区别
java·json
虎头金猫5 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
胡写代码5 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖5 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时5 天前
01-06-A-JVM排查实战详解
java·jvm
伞伞悦读5 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
vipxieliang5 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot