使用多线程+网络编程实现一个服务器对多个客户端
在该程序中用到的知识点
- java的BIO
- ServerSocket和Socket 网络编程
- 多线程的知识(个人认为重要)
实现的思路
服务器端(使用多个线程)
- 在客户端需要有一个集合来存储已经连接上的客户端, 如果客户端断开连接则需要从集合中删除
- 创建一个线程来处理客户端的连接
- 每一个客户端的连接都需要一个线程来接收客户端的请求
- 使用主线程来给客户端发送数据(轮询客户端集合中的Socket给客户端发送数据)
客户端(使用两个线程)
- 首先创建一个线程来接收服务器端的数据
- 使用主线程来给服务器端发送数据
服务器端:
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 }
标签:Java,socket,编程,catch,new,socketList,Socket,客户端 From: https://www.cnblogs.com/szmtjs10/p/17806477.html