Skip to content

Latest commit

 

History

History
316 lines (315 loc) · 15 KB

SpringBoot整合Socket.md

File metadata and controls

316 lines (315 loc) · 15 KB
1.引入web依赖: (用于提供日志依赖的支持)
	<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
2.Socket服务端:
	[1]手动启动版: (需手动启动;占用主线程;)
        public class Server {
            private static Logger logger = LoggerFactory.getLogger(Server.class);
            // 监听的端口号
            private static final int PORT = 8081;
            public static void main(String[] args) {
                Server server = new Server();
                server.init();
            }
            private void init() {
                try {
                    // new ServerSocket(port[,len]): len为连接请求的队列长度,超过则拒绝
                    ServerSocket serverSocket = new ServerSocket(PORT);
                    logger.info("Server Start... ");
                    while (true) {
                        //阻塞等待,若请求队列中有连接,则取出一个
                        Socket client = serverSocket.accept();
                        // 处理取到的连接
                        hand(client);
                    }
                } catch (Exception e) {
                    logger.error("服务器异常: " + e.getMessage());
                }
            }
            private void hand(Socket socket) {
                try {
                    // 读取客户端数据
                    BufferedReader input =
                            new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    // 这里要注意和客户端输出流的写方法对应,否则会抛 EOFException
                    String clientInputStr = input.readLine();
                    // 处理客户端数据
                    logger.info("客户端发过来的内容:" + clientInputStr);
                    // 向客户端回复信息
                    PrintStream out = new PrintStream(socket.getOutputStream());
                    logger.info("请输入:");
                    // 发送键盘输入的一行
                    String s = new BufferedReader(new InputStreamReader(System.in)).readLine();
                    out.println(s);
                    // 关闭流
                    out.close();
                    input.close();
                } catch (Exception e) {
                    logger.error("服务器 run 异常: " + e.getMessage());
                } finally {
                    if (socket != null) {
                        try {
                            socket.close();
                        } catch (Exception e) {
                            logger.error("服务端 finally 异常:" + e.getMessage());
                        }
                    }
                }
            }
        }
	[2]单线程自动启动版: (随项目启动而启动;不占用主线程,另起一个线程来运行服务)
        @Component
        public class Server1 {
            private static Logger logger = LoggerFactory.getLogger(Server1.class);
            //监听的端口号
            private static final int PORT = 8081;
            // @Component+@PostConstruct实现服务端随项目启动而启动
            @PostConstruct
            private void start() {
                SocketThread socketThread = new SocketThread();
                socketThread.start();
            }
            public static class SocketThread extends Thread {
                private ServerSocket serverSocket;
                public SocketThread() {
                    try {
                        this.serverSocket = new ServerSocket(PORT);
                        logger.info("Server1 Start...");
                    } catch (IOException e) {
                        logger.error("服务器异常: " + e.getMessage());
                    }
        
                }
                @Override
                public void run() {
                    while (!this.isInterrupted()) {
                        //线程未中断则执行循环 
                        try {
                            Socket client = serverSocket.accept();
                            hand(client);
                        } catch (IOException e) {
                            logger.error("服务器异常: " + e.getMessage());
                        }
                    }
                }
                private void hand(Socket socket) {
                    try {
                        // 读取客户端数据
                        BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        //这里要注意和客户端输出流的写方法对应,否则会抛 EOFException
                        String clientInputStr = input.readLine();
                        // 处理客户端数据
                        logger.info("客户端发过来的内容:" + clientInputStr);
                        // 向客户端回复信息
                        PrintStream out = new PrintStream(socket.getOutputStream());
                        logger.info("请输入:");
                        // 发送键盘输入的一行
                        String s = new BufferedReader(new InputStreamReader(System.in)).readLine();
                        out.println(s);
                        //关闭流
                        out.close();
                        input.close();
                    } catch (Exception e) {
                        logger.info("服务器 run 异常: " + e.getMessage());
                    } finally {
                        if (socket != null) {
                            try {
                                socket.close();
                            } catch (Exception e) {
                                logger.info("服务端 finally 异常:" + e.getMessage());
                            }
                        }
                    }
                }
            }
        }
	[3]自动启动多线程处理版: (随项目启动而启动;不占用主线程,另起单个线程来运行服务,多线程处理)
        @Component
        public class Server2 {
            private static Logger logger = LoggerFactory.getLogger(Server2.class);
            private static final int PORT = 8081;//监听的端口号
            // @Component+@PostConstruct实现服务端随项目启动而启动
            @PostConstruct
            private void start() {
                SocketThread socketThread = new SocketThread();
                socketThread.start();
            }
            public static class SocketThread extends Thread {
                private ServerSocket serverSocket;
                public SocketThread() {
                    try {
                        this.serverSocket = new ServerSocket(PORT);
                        logger.info("Server2 Start...");
                    } catch (IOException e) {
                        logger.error("服务器异常: " + e.getMessage());
                    }
                }
                @Override
                public void run() {
                    while (!this.isInterrupted()) {
                        //线程未中断则执行循环 
                        try {
                            Socket client = serverSocket.accept();
                            new HandlerThread(client);
                        } catch (IOException e) {
                            logger.error("服务器异常: " + e.getMessage());
                        }
                    }
                }
            }
            public static class HandlerThread implements Runnable {
                private Socket socket;
                HandlerThread(Socket client) {
                    socket = client;
                    new Thread(this).start();
                }
                @Override
                public void run() {
                    try {
                        // 读取客户端数据
                        BufferedReader input =
                                new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        //这里要注意和客户端输出流的写方法对应,否则会抛 EOFException
                        String clientInputStr = input.readLine();
                        // 处理客户端数据
                        logger.info("客户端发过来的内容:" + clientInputStr);
                        // 向客户端回复信息
                        PrintStream out = new PrintStream(socket.getOutputStream());
                        logger.info("请输入:");
                        // 发送键盘输入的一行
                        String s = new BufferedReader(new InputStreamReader(System.in)).readLine();
                        out.println(s);
                        //关闭流
                        out.close();
                        input.close();
                    } catch (Exception e) {
                        logger.info("服务器 run 异常: " + e.getMessage());
                    } finally {
                        if (socket != null) {
                            try {
                                socket.close();
                            } catch (Exception e) {
                                logger.info("服务端 finally 异常:" + e.getMessage());
                            }
                        }
                    }
                }
            }
        }
	[4]自动启动多线程处理优化版: (解决上一版本无限创建线程的问题)
        @Component
        public class Server3 {
            private static Logger logger = LoggerFactory.getLogger(Server3.class);
            //监听的端口号
            private static final int PORT = 8081;
            // @Component+@PostConstruct实现服务端随项目启动而启动
            @PostConstruct
            private void start() {
                SocketThread socketThread = new SocketThread();
                socketThread.start();
            }
            public static class SocketThread extends Thread {
                private ServerSocket serverSocket;
                public SocketThread() {
                    try {
                        this.serverSocket = new ServerSocket(PORT);
                        logger.info("Server Start...");
                    } catch (IOException e) {
                        logger.error("服务器异常: " + e.getMessage());
                    }
                }
                @Override
                public void run() {
                    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
                    while (!this.isInterrupted()) {
                        //线程未中断则执行循环 
                        try {
                            Socket socket = serverSocket.accept();
                            fixedThreadPool.execute(new Runnable() {
                                @Override
                                public void run() {
                                    try {
                                        // 读取客户端数据
                                        BufferedReader input =
                                                new BufferedReader(new InputStreamReader(socket.getInputStream()));
                                        //这里要注意和客户端输出流的写方法对应,否则会抛 EOFException
                                        String clientInputStr = input.readLine();
                                        // 处理客户端数据
                                        logger.info("客户端发过来的内容:" + clientInputStr);
                                        // 向客户端回复信息
                                        PrintStream out = new PrintStream(socket.getOutputStream());
                                        logger.info("请输入:");
                                        // 发送键盘输入的一行
                                        String s = new BufferedReader(new InputStreamReader(System.in)).readLine();
                                        out.println(s);
                                        //关闭流
                                        out.close();
                                        input.close();
                                    } catch (Exception e) {
                                        logger.info("服务器 run 异常: " + e.getMessage());
                                    } finally {
                                        if (socket != null) {
                                            try {
                                                socket.close();
                                            } catch (Exception e) {
                                                logger.info("服务端 finally 异常:" + e.getMessage());
                                            }
                                        }
                                    }
                                }
                            });
                        } catch (IOException e) {
                            logger.error("服务器异常: " + e.getMessage());
                        }
                    }
                }
            }
        }
3.通用客户端:
    public class Client {
        // 服务端端口
        private static final int PORT = 8081;
        // 服务端IP
        private static final String HOST = "localhost";
        private static Logger logger = LoggerFactory.getLogger(Client.class);
        public static void main(String[] args) {
            logger.info("Client Start...");
            while (true) {
                Socket socket = null;
                try {
                    //创建一个套接字对象并将其连接到指定主机上的指定端口号
                    socket = new Socket(HOST, PORT);
                    //读取服务器端数据
                    BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    //向服务器端发送数据
                    PrintStream out = new PrintStream(socket.getOutputStream());
                    logger.info("请输入: ");
                    String str = new BufferedReader(new InputStreamReader(System.in)).readLine();
                    out.println(str);
                    String ret = input.readLine();
                    logger.info("服务器端返回过来的是: " + ret);
                    // 如接收到 "OK" 则断开连接
                    if ("OK".equals(ret)) {
                        logger.info("客户端正在关闭连接...");
                        Thread.sleep(500);
                        break;
                    }
                    out.close();
                    input.close();
                } catch (Exception e) {
                    logger.info("客户端异常:" + e.getMessage());
                } finally {
                    if (socket != null) {
                        try {
                            socket.close();
                        } catch (IOException e) {
                            logger.info("客户端 finally 异常:" + e.getMessage());
                        }
                    }
                }
            }
        }
    }