首页 > 编程语言 > 详细

基于BIO的多线程客户端服务器通信案例

时间:2021-06-30 18:27:07      阅读:14      评论:0      收藏:0      [点我收藏+]

服务端实现

 主程序入口

  1 package server;
  2 
  3 import java.io.BufferedWriter;
  4 import java.io.IOException;
  5 import java.io.OutputStreamWriter;
  6 import java.io.Writer;
  7 import java.net.ServerSocket;
  8 import java.net.Socket;
  9 import java.util.HashMap;
 10 import java.util.Map;
 11 import java.util.concurrent.ExecutorService;
 12 import java.util.concurrent.Executors;
 13 
 14 public class ChatServer {
 15 
 16     private int DEFAULT_PORT = 8888;
 17     private final String QUIT = "quit";
 18 
 19     private ExecutorService executorService;
 20     private ServerSocket serverSocket;
 21     private Map<Integer, Writer> connectedClients;
 22 
 23     public ChatServer() {
 24         executorService = Executors.newFixedThreadPool(10);
 25         connectedClients = new HashMap<>();
 26     }
 27 
 28     public synchronized void addClient(Socket socket) throws IOException {
 29         if (socket != null) {
 30             int port = socket.getPort();
 31             BufferedWriter writer = new BufferedWriter(
 32                     new OutputStreamWriter(socket.getOutputStream())
 33             );
 34             connectedClients.put(port, writer);
 35             System.out.println("客户端[" + port + "]已连接到服务器");
 36         }
 37     }
 38 
 39     public synchronized void removeClient(Socket socket) throws IOException {
 40         if (socket != null) {
 41             int port = socket.getPort();
 42             if (connectedClients.containsKey(port)) {
 43                 connectedClients.get(port).close();
 44             }
 45             connectedClients.remove(port);
 46             System.out.println("客户端[" + port + "]已断开连接");
 47         }
 48     }
 49 
 50     public synchronized void forwardMessage(Socket socket, String fwdMsg) throws IOException {
 51         for (Integer id : connectedClients.keySet()) {
 52             if (!id.equals(socket.getPort())) {
 53                 Writer writer = connectedClients.get(id);
 54                 writer.write(fwdMsg);
 55                 writer.flush();
 56             }
 57         }
 58     }
 59 
 60     public boolean readyToQuit(String msg) {
 61         return QUIT.equals(msg);
 62     }
 63 
 64     public synchronized void close() {
 65         if (serverSocket != null) {
 66             try {
 67                 serverSocket.close();
 68                 System.out.println("关闭serverSocket");
 69             } catch (IOException e) {
 70                 e.printStackTrace();
 71             }
 72         }
 73     }
 74 
 75     public void start() {
 76 
 77         try {
 78             // 绑定监听端口
 79             serverSocket = new ServerSocket(DEFAULT_PORT);
 80             System.out.println("启动服务器,监听端口:" + DEFAULT_PORT + "...");
 81 
 82             while (true) {
 83                 // 等待客户端连接
 84                 Socket socket = serverSocket.accept();
 85                 // 创建ChatHandler线程
 86                 executorService.execute(new ChatHandler(this, socket));
 87             }
 88 
 89         } catch (IOException e) {
 90             e.printStackTrace();
 91         } finally {
 92             close();
 93         }
 94     }
 95 
 96     public static void main(String[] args) {
 97         ChatServer server = new ChatServer();
 98         server.start();
 99     }
100 
101 }

处理客户端请求

 1 package server;
 2 
 3 import java.io.*;
 4 import java.net.Socket;
 5 
 6 public class ChatHandler implements Runnable {
 7 
 8     private ChatServer server;
 9     private Socket socket;
10 
11     public ChatHandler(ChatServer server, Socket socket) {
12         this.server = server;
13         this.socket = socket;
14     }
15 
16     @Override
17     public void run() {
18         try {
19             // 存储新上线用户
20             server.addClient(socket);
21 
22             // 读取用户发送的消息
23             BufferedReader reader = new BufferedReader(
24                     new InputStreamReader(socket.getInputStream())
25             );
26 
27             String msg = null;
28             while ((msg = reader.readLine()) != null) {
29                 String fwdMsg = "客户端[" + socket.getPort() + "]: " + msg + "\n";
30                 System.out.print(fwdMsg);
31 
32                 // 将消息转发给聊天室里在线的其他用户
33                 server.forwardMessage(socket, fwdMsg);
34 
35                 // 检查用户是否准备退出
36                 if (server.readyToQuit(msg)) {
37                     break;
38                 }
39             }
40         } catch (IOException e) {
41             e.printStackTrace();
42         } finally {
43             try {
44                 server.removeClient(socket);
45             } catch (IOException e) {
46                 e.printStackTrace();
47             }
48         }
49     }
50 }

 

 

客户端实现

主程序入口

 1 package client;
 2 
 3 import java.io.*;
 4 import java.net.Socket;
 5 
 6 public class ChatClient {
 7 
 8     private final String DEFAULT_SERVER_HOST = "127.0.0.1";
 9     private final int DEFAULT_SERVER_PORT = 8888;
10     private final String QUIT = "quit";
11 
12     private Socket socket;
13     private BufferedReader reader;
14     private BufferedWriter writer;
15 
16     // 发送消息给服务器
17     public void send(String msg) throws IOException {
18         if (!socket.isOutputShutdown()) {
19             writer.write(msg + "\n");
20             writer.flush();
21         }
22     }
23 
24     // 从服务器接收消息
25     public String receive() throws IOException {
26         String msg = null;
27         if (!socket.isInputShutdown()) {
28             msg = reader.readLine();
29         }
30         return msg;
31     }
32 
33     // 检查用户是否准备退出
34     public boolean readyToQuit(String msg) {
35         return QUIT.equals(msg);
36     }
37 
38     public void close() {
39         if (writer != null) {
40             try {
41                 System.out.println("关闭socket");
42                 writer.close();
43             } catch (IOException e) {
44                 e.printStackTrace();
45             }
46         }
47     }
48 
49     public void start() {
50 
51         try {
52             // 创建socket
53             socket = new Socket(DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT);
54 
55             // 创建IO流
56             reader = new BufferedReader(
57                     new InputStreamReader(socket.getInputStream())
58             );
59             writer = new BufferedWriter(
60                     new OutputStreamWriter(socket.getOutputStream())
61             );
62 
63             // 处理用户的输入
64             new Thread(new UserInputHandler(this)).start();
65 
66             // 读取服务器转发的消息
67             String msg = null;
68             while ((msg = receive()) != null) {
69                 System.out.println(msg);
70             }
71         } catch (IOException e) {
72             e.printStackTrace();
73         } finally {
74             close();
75         }
76     }
77 
78     public static void main(String[] args) {
79         ChatClient chatClient = new ChatClient();
80         chatClient.start();
81     }
82 }

用户输入任务线程

 1 package client;
 2 
 3 import client.ChatClient;
 4 import java.io.*;
 5 
 6 public class UserInputHandler implements Runnable {
 7 
 8     private ChatClient chatClient;
 9 
10     public UserInputHandler(ChatClient chatClient) {
11         this.chatClient = chatClient;
12     }
13 
14     @Override
15     public void run() {
16         try {
17             // 等待用户输入消息
18             BufferedReader consoleReader =
19                     new BufferedReader(new InputStreamReader(System.in));
20             while (true) {
21                 String input = consoleReader.readLine();
22 
23                 // 向服务器发送消息
24                 chatClient.send(input);
25 
26                 // 检查用户是否准备退出
27                 if (chatClient.readyToQuit(input)) {
28                     break;
29                 }
30             }
31         } catch (IOException e) {
32             e.printStackTrace();
33         }
34     }
35 }

 

基于BIO的多线程客户端服务器通信案例

原文:https://www.cnblogs.com/lpzh/p/14953974.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!