• 【Java】BIO,NIO,AIO聊天室示例


    BIO,NIO,AIO聊天室示例

    几个概念

    • 同步: 发送方发送请求之后,需要等接收方发回响应后才接着发
    • 异步: 发送方发送请求之后,不等待接收方响应,继续发送下一个,系统内核完成请求后主动通知
    • 阻塞: 在调用结果返回之前,当前线程会被挂起,需等到得到结果后才会返回。线程在此过程中不进行任何其他处理。
    • 非阻塞: 调用结果不会立即返回,当前线程也不会被挂起,而是立即返回执行下一个调用。

    socket连接


    连接过程:

    服务器端:

    1. 创建socket,绑定端口
    2. 开始监听
    3. 等待并接收客户端连接请求,返回新socket
    4. 由新socket与客户端进行交互
    5. 关闭连接

    客户端:

    1. 创建socket
    2. 连接服务器与io交互
    3. 关闭连接

    示例代码:

    服务器端:

    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.nio.charset.StandardCharsets;
    
    public class ChatServer {
    
        /**
         * 监听端口号
         */
        private int port = 8081;
    
        public ChatServer() {
        }
    
        public ChatServer(int port) {
            this.port = port;
        }
    
        public void service() {
            try {
                System.out.println("服务器开始建立连接");
                // 建立服务器连接
                ServerSocket serverSocket = new ServerSocket(port);
                System.out.println("服务器开始监听");
                // 开始监听
                Socket socket = serverSocket.accept();
                // 获取输出流,向客户端发送信息
                OutputStream outputStream = socket.getOutputStream();
                BufferedReader reader = null;
                try {
                    // 获取输入流,读取客户端传过来的信息
                    reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    String line = "";
                    while ((line = reader.readLine()) != null) {
                        System.out.println("从客户端接收到一条消息,内容为:" + line);
                    }
                    // 发送消息给客户端
                    outputStream.write("我接收到了".getBytes(StandardCharsets.UTF_8));
                } finally {
                    // 关闭流和连接
                    if(reader != null) {
                        reader.close();
                    }
                    if(outputStream != null) {
                        outputStream.close();
                    }
                    if(socket != null) {
                        socket.close();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            ChatServer chatServer = new ChatServer();
            chatServer.service();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    客户端:

    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.nio.charset.StandardCharsets;
    
    public class ChatClient {
    
        private int port = 8080;
    
        public ChatClient() {
        }
    
        public ChatClient(int port) {
            this.port = port;
        }
    
        private void consumer() {
            System.out.println("客户端开始发送数据");
            try {
                Socket client = new Socket("localhost", 8081);
                OutputStream outputStream = client.getOutputStream();
                try {
                    outputStream.write("这里是8080端口".getBytes(StandardCharsets.UTF_8));
                } finally {
                    if(outputStream != null) {
                        outputStream.close();
                    }
                    if(client != null) {
                        client.close();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            ChatClient client = new ChatClient();
            client.consumer();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    运行结果:
    在这里插入图片描述

    在这里插入图片描述

    BIO(同步阻塞IO模式)

    每一个客户端的请求都需要服务端开启一个线程处理。

    package com.alone.study.chat.bio;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.nio.charset.StandardCharsets;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    
    import static java.util.concurrent.Executors.newFixedThreadPool;
    
    public class ChatServer {
    
        /**
         * 监听端口号
         */
        private int port = 8081;
        /**
         * 处理socket的线程池
         */
        private static final ExecutorService EXECUTOR_SERVICE = newFixedThreadPool(10);
        private List<Socket> sockets = new ArrayList<>(10);
    
        public ChatServer() {
        }
    
        public ChatServer(int port) {
            this.port = port;
        }
    
        public void service() {
            try {
                System.out.println("服务器开始建立连接");
                // 建立服务器连接
                ServerSocket serverSocket = new ServerSocket(port);
                System.out.println("服务器开始监听");
                // 开始监听
                Socket socket = serverSocket.accept();
                sockets.add(socket);
                EXECUTOR_SERVICE.submit(new SocketThread(socket));
                Thread.sleep(2000);
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            } finally {
                if(sockets != null) {
                    for (Socket socket : sockets) {
                        if(socket != null) {
                            try {
                                socket.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            ChatServer chatServer = new ChatServer();
            chatServer.service();
        }
    
        private class SocketThread implements Runnable {
    
            private Socket socket;
    
            public SocketThread() {
            }
    
            public SocketThread(Socket socket) {
                this.socket = socket;
            }
    
            @Override
            public void run() {
                System.out.println("开始处理来自" + socket.getRemoteSocketAddress() + "的请求");
                // 接收客户端的消息
                readFromClient();
                // 回复客户端说已收到
                sendToClient();
            }
    
            private void sendToClient() {
                OutputStream outputStream = null;
                // 回复客户端
                try {
                    outputStream = socket.getOutputStream();
                    // 发送消息给客户端
                    outputStream.write("我接收到了".getBytes(StandardCharsets.UTF_8));
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    // 关闭流和连接
                    if(outputStream != null) {
                        try {
                            outputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
    
            private void readFromClient() {
                // 接收客户端的数据
                BufferedReader reader = null;
                try {
                    System.out.println("开始获取客户端接收的消息");
                    // 获取输入流,读取客户端传过来的信息
                    reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    String line = "";
                    while ((line = reader.readLine()) != null) {
                        System.out.println("从客户端接收到一条消息,内容为:" + line);
                    }
                    System.out.println("结束获取客户端接收的消息");
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    // 关闭流和连接
                    if(reader != null) {
                        try {
                            reader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    package com.alone.study.chat.bio;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.nio.charset.StandardCharsets;
    import java.util.concurrent.ExecutorService;
    
    import static java.util.concurrent.Executors.newFixedThreadPool;
    
    public class ChatClient {
    
        private int port = 8080;
        private static final ExecutorService EXECUTOR_SERVICE = newFixedThreadPool(1);
    
        public ChatClient() {
        }
    
        public ChatClient(int port) {
            this.port = port;
        }
    
        private void consumer() {
            System.out.println("客户端开始发送数据");
            try {
                Socket client = new Socket("localhost", 8081);
                OutputStream outputStream = client.getOutputStream();
                try {
                    outputStream.write("这里是8080端口".getBytes(StandardCharsets.UTF_8));
                    System.out.println("客户端结束发送数据");
                } finally {
                    if(outputStream != null) {
                        outputStream.close();
                    }
                    if(client != null) {
                        client.close();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            ChatClient client = new ChatClient();
            client.consumer();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    不太理解上面这个服务端为啥会报错。

    NIO

    nio学习笔记

    to be continue…

    参考资料

    1.java的socket连接,聊天室通信实现
    2. 简述Socket连接的过程
    3. Java网络编程之通过代码实现Socket通信
    4. BIO、NIO、AIO实现聊天室功能
    5. 同步、异步、阻塞、非阻塞傻傻分不清?

  • 相关阅读:
    MySQL进阶(回望MySQL)——从数据资产谈起 & MySQL的DOS命令、常用数据类型、SQL语句的分类 & SQL函数
    el-cascader三级联动懒加载回显问题
    02 【基础篇-vim编辑器 网络配置 远程登录】
    [附源码]java毕业设计医院管理系统
    我的创作纪念日--码农阿豪
    数据库系统原理与应用教程(077)—— MySQL 练习题:操作题 168-172(二十一):综合练习
    【智能家居项目】裸机版本——字体子系统 | 显示子系统
    金仓数据库KingbaseES客户端应用参考手册--21. kbbadger
    vue看项目文件判断配置方法
    Java遍历目录下的所有文件
  • 原文地址:https://blog.csdn.net/qq_41279172/article/details/126693984