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 }
原文:https://www.cnblogs.com/lpzh/p/14953974.html