Java网络编程实现一(服务器)对多(客户端)

发布时间 2023-11-02 22:18:29作者: szmtjs10

使用多线程+网络编程实现一个服务器对多个客户端

在该程序中用到的知识点

  1. java的BIO
  2. ServerSocket和Socket 网络编程
  3. 多线程的知识(个人认为重要)

实现的思路

服务器端(使用多个线程)

  1. 在客户端需要有一个集合来存储已经连接上的客户端, 如果客户端断开连接则需要从集合中删除
  2. 创建一个线程来处理客户端的连接
  3. 每一个客户端的连接都需要一个线程来接收客户端的请求
  4. 使用主线程来给客户端发送数据(轮询客户端集合中的Socket给客户端发送数据)

客户端(使用两个线程)

  1. 首先创建一个线程来接收服务器端的数据
  2. 使用主线程来给服务器端发送数据

 

服务器端:

  1 package 菜鸟教程.网络编程.多线程网络编程;
  2 
  3 import java.io.*;
  4 import java.net.ServerSocket;
  5 import java.net.Socket;
  6 import java.net.SocketException;
  7 import java.util.ArrayList;
  8 import java.util.List;
  9 import java.util.Scanner;
 10 
 11 public class Server {
 12 
 13     public static void main(String[] args) {
 14         List<Socket> socketList = new ArrayList<>();
 15 
 16         // 开启线程接收客户端的连接
 17         new Thread(new AcceptSocket(socketList)).start();
 18 
 19         while (true) {
 20             Scanner scanner = new Scanner(System.in);
 21             String sendInfo = scanner.nextLine();
 22             // 循环向所有的客户端发送消息
 23             socketList.forEach(socket -> {
 24                 try {
 25                     PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
 26                     printWriter.println(sendInfo);
 27                     printWriter.flush();
 28                 } catch (SocketException e) {
 29                     System.out.println(1);
 30                 } catch (IOException e) {
 31                     e.printStackTrace();
 32                 }
 33             });
 34         }
 35     }
 36 }
 37 
 38 // 接收客户端Socket线程
 39 class AcceptSocket implements Runnable {
 40 
 41     List<Socket> socketList;
 42 
 43     public AcceptSocket(List<Socket> socketList) {
 44         this.socketList = socketList;
 45     }
 46 
 47     @Override
 48     public void run() {
 49         ServerSocket serverSocket = null;
 50         try {
 51             serverSocket = new ServerSocket(9000);
 52             System.out.println("监听客户端的连接");
 53             // 循环接收客户端的请求
 54             while (true) {
 55                 Socket socket = serverSocket.accept();
 56                 // 接收到后加入到 socketList
 57                 socketList.add(socket);
 58                 // 开启处理客户端线程
 59                 new Thread(new HandleSocket(socket, socketList)).start();
 60             }
 61         } catch (SocketException e) {
 62             System.out.println(2);
 63         } catch (IOException e) {
 64             e.printStackTrace();
 65         } finally {
 66             // 关闭连接
 67             try {
 68                 if (null != serverSocket) {
 69                     serverSocket.close();
 70                 }
 71             } catch (IOException e) {
 72                 e.printStackTrace();
 73             }
 74 
 75         }
 76     }
 77 }
 78 
 79 // 处理客户端Socket线程
 80 class HandleSocket implements Runnable {
 81 
 82     Socket socket;
 83 
 84     List<Socket> socketList;
 85 
 86     public HandleSocket(Socket socket, List<Socket> socketList) {
 87         this.socket = socket;
 88         this.socketList = socketList;
 89     }
 90 
 91     @Override
 92     public void run() {
 93         BufferedReader bufferedReader = null;
 94         try {
 95             // 读取客户端发来的数据
 96             bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 97             System.out.println("等待读取客户端:" + socket.getLocalAddress().toString().substring(1) + ":" + socket.getPort() + " 的消息");
 98             while (true) {
 99                 String clientInfo = bufferedReader.readLine();
100                 System.out.println(socket.getLocalAddress().toString().substring(1) + ":" + socket.getPort() + "发送的消息是:" + clientInfo);
101             }
102         } catch (SocketException e) {
103             // 强制关闭连接后的处理
104             System.out.println(socket.getLocalAddress().toString().substring(1) + ":" + socket.getPort() + "断开连接");
105             // 将该连接从socketList中移除
106             socketList.remove(socket);
107         } catch (IOException e) {
108             e.printStackTrace();
109         } finally {
110 
111             // 关闭连接
112             try {
113                 if (null != bufferedReader) {
114                     bufferedReader.close();
115                 }
116                 if (null != socket) {
117                     bufferedReader.close();
118                 }
119             } catch (IOException e) {
120                 e.printStackTrace();
121             }
122 
123         }
124     }
125 }

 

客户端

 1 package 菜鸟教程.网络编程.多线程网络编程;
 2 
 3 import java.io.*;
 4 import java.net.Socket;
 5 import java.net.SocketException;
 6 import java.util.Scanner;
 7 
 8 public class Client {
 9     public static void main(String[] args) {
10         Scanner scanner = new Scanner(System.in);
11         Socket socket = null;
12         PrintWriter printWriter = null;
13         try {
14             socket = new Socket("localhost", 9000);
15             printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
16 
17             //开启线程接收服务端的消息
18             new Thread(new AcceptServer(socket)).start();
19             System.out.println("可以给服务器端发送数据了");
20             while (true) {
21                 // 给服务端发送消息
22                 String sendInfo = scanner.nextLine();
23                 printWriter.println(sendInfo);
24                 printWriter.flush();
25             }
26 
27         } catch (IOException e) {
28             e.printStackTrace();
29         } finally {
30             // 关闭连接
31             try {
32                 if (null != socket) {
33                     socket.close();
34                 }
35                 if (null != printWriter) {
36                     printWriter.close();
37                 }
38             } catch (IOException e) {
39                 e.printStackTrace();
40             }
41 
42         }
43     }
44 }
45 
46 class AcceptServer implements Runnable {
47 
48     Socket socket;
49 
50     public AcceptServer(Socket socket) {
51         this.socket = socket;
52     }
53 
54     @Override
55     public void run() {
56         BufferedReader bufferedReader = null;
57         try {
58             bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
59             while (true) {
60                 String serverInfo = bufferedReader.readLine();
61                 System.out.println("服务器的消息为:" + serverInfo);
62             }
63         } catch (SocketException e) {
64             System.out.println("服务器异常关闭");
65             // 退出
66             System.exit(0);
67         } catch (IOException e) {
68             e.printStackTrace();
69         } finally {
70             // 关闭连接
71             try {
72                 if (null != bufferedReader) {
73                     bufferedReader.close();
74                 }
75                 if (null != socket) {
76                     socket.close();
77                 }
78             } catch (IOException e) {
79                 e.printStackTrace();
80             }
81         }
82     }
83 }