TCP通信实战案例-即时通信

设计思路

  • 即时通信, 是指一个客户端的消息发出去, 其他客户端可以接收到
  • 即时通信需要进行端口转发的设计思想
  • 服务端需要把在线的Socket管道存储起来
  • 一旦收到一个消息要推送给其他管道

代码实现

客户端

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        /**
         * 创建Socket通信管道请求有服务端的连接
         * 参数一:服务端的IP地址
         * 参数二:服务端的端口
         */
        Socket socket = new Socket("127.0.0.1",9999);

        //创建一个独立的线程专门负责这个客户端的读消息(服务端随时可能转发消息过来)
        new ClientReaderThread(socket).start();

        //从socket通信管道中得到一个字节输出流,负责发送数据
        OutputStream os = socket.getOutputStream();

        //把字节流包装成打印流
        PrintStream ps = new PrintStream(os);

        Scanner sc = new Scanner(System.in);
        while (true){
            System.out.println("请说:");
            String msg = sc.nextLine();

            ps.println(msg);
            ps.flush();
        }
    }
}

class ClientReaderThread extends Thread{
    private Socket socket;

    public ClientReaderThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try{
            //从socket通信管道中得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流接收消息
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String line;
            while ((line = br.readLine()) != null) {
                System.out.println("收到消息: " + line);
            }
        } catch (Exception e){
            System.out.println("服务端不转发你的消息了,关闭了通信管道");
        }

    }
}

服务端

public class ServerDemo {
    //定义一个静态的List集合存储当前全部在线的socket管道
    public static List<Socket> allOnlineSocket = new ArrayList<>();

    public static void main(String[] args) throws IOException {
        //注册端口
        ServerSocket serverSocket = new ServerSocket(9999);

        while (true) {
            //每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取信息
            Socket socket = serverSocket.accept();
            System.out.println(socket.getRemoteSocketAddress() + "上线了");
            allOnlineSocket.add(socket);
            new ServerReaderThread(socket).start();
        }
    }
}

class ServerReaderThread extends Thread {
    private Socket socket;

    public ServerReaderThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            //从socket通信管道中得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流接收消息
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(socket.getRemoteSocketAddress() + "发来了" + line);
                //把这个消息进行端口转发给全部客户端socket管道
                sendMsgToALL(line, socket);
            }
        } catch (Exception e) {
            System.out.println(socket.getRemoteSocketAddress() + "下线了");
            ServerDemo.allOnlineSocket.remove(socket);
        }

    }

    private void sendMsgToALL(String msg, Socket socket) throws IOException {
        for (Socket s : ServerDemo.allOnlineSocket) {
            if (s != socket) {
                PrintStream ps = new PrintStream(s.getOutputStream());
                ps.println(msg);
                ps.flush();
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值