一、聊天室结构图
二、代码
1 package com.demo; 2 3 import org.junit.Test; 4 5 import java.io.*; 6 import java.net.InetAddress; 7 import java.net.InetSocketAddress; 8 import java.net.ServerSocket; 9 import java.net.Socket; 10 import java.util.Map; 11 import java.util.Scanner; 12 import java.util.concurrent.ConcurrentHashMap; 13 14 15 /** 16 * BIO 聊天是demo 17 * 用户可以登陆聊天室,发送消息,和收到其他人发送的消息 18 * 19 * 用户第一次登录,需要设置自己的用户名 20 */ 21 public class BIOChatDemo { 22 23 // 发数据到用户流集合 24 Map<String, BufferedWriter> map = new ConcurrentHashMap<>(); 25 26 @Test 27 public void server() { 28 ServerSocket serverSocket = null; 29 try { 30 // 创建ServerSocket 31 serverSocket = new ServerSocket(); 32 InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 9999); 33 serverSocket.bind(inetSocketAddress); 34 35 while (true) { 36 // 阻塞,获取连接 37 Socket socket = serverSocket.accept(); 38 new Thread(() -> { 39 BufferedReader bufferedReader = null; 40 BufferedWriter bufferedWriter = null; 41 String username = null; 42 try { 43 // 获取输入流 44 bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 45 bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 46 47 // 接收数据 48 String s = bufferedReader.readLine(); 49 username = s; 50 String address = socket.getInetAddress().getHostAddress(); 51 int port = socket.getPort(); 52 map.put(username, bufferedWriter); 53 String prefix = username + "(" + address + ":" + port +"):"; 54 System.out.println("客户端:" + prefix +" 登录"); 55 bufferedWriter.write("欢迎登录-" + prefix +"\n"); 56 bufferedWriter.flush(); 57 58 while ((s = bufferedReader.readLine()) != null) { 59 // 广播给其他客户端 60 for (Map.Entry<String, BufferedWriter> entry : map.entrySet()) { 61 String k = entry.getKey(); 62 BufferedWriter bw = entry.getValue(); 63 // 不发给自己 64 if (!prefix.startsWith(k)) { 65 bw.write(prefix + s + "\n"); 66 bw.flush(); 67 } 68 } 69 } 70 System.out.println("客户端:" + prefix +" 断开连接"); 71 } catch (IOException e) { 72 e.printStackTrace(); 73 } finally { 74 75 // 移除队列 76 if(map.keySet().contains(username)) { 77 map.remove(username); 78 } 79 // 关闭资源 80 if (bufferedWriter != null) { 81 try { 82 bufferedWriter.close(); 83 } catch (IOException e) { 84 e.printStackTrace(); 85 } 86 } 87 if (bufferedReader != null) { 88 try { 89 bufferedReader.close(); 90 } catch (IOException e) { 91 e.printStackTrace(); 92 } 93 } 94 if (socket != null) { 95 try { 96 socket.close(); 97 } catch (IOException e) { 98 e.printStackTrace(); 99 } 100 } 101 } 102 103 }).start(); 104 } 105 106 } catch (IOException e) { 107 e.printStackTrace(); 108 } finally { 109 if (serverSocket != null) { 110 try { 111 serverSocket.close(); 112 } catch (IOException e) { 113 e.printStackTrace(); 114 } 115 } 116 } 117 118 } 119 120 @Test 121 public void client() { 122 Socket socket = null; 123 BufferedReader bufferedReader = null; 124 BufferedWriter bufferedWriter = null; 125 try { 126 // 创建Socket 127 socket = new Socket(); 128 InetAddress inetAddress = InetAddress.getByName("127.0.0.1"); 129 // 客户端socket不绑定端口,本地会随机产生一个端口 130 // InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 19994); 131 // socket.bind(inetSocketAddress); 132 // 连接 133 socket.connect(new InetSocketAddress("127.0.0.1", 9999)); 134 135 // 获取输出流 136 bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 137 bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 138 139 // 循环写出数据,询问时间 140 BufferedWriter finalBufferedWriter = bufferedWriter; 141 new Thread(() -> { 142 try { 143 Scanner scanner = new Scanner(System.in); 144 System.out.println("请输入用户名:"); 145 while (scanner.hasNext()) { 146 finalBufferedWriter.write(scanner.next() +"\n"); 147 finalBufferedWriter.flush(); 148 } 149 } catch (IOException e) { 150 e.printStackTrace(); 151 } 152 }).start(); 153 154 // 接收数据 155 String s = null; 156 // 输入不知道什么时候到达末尾,所以这里会阻塞 157 while ((s = bufferedReader.readLine()) != null) { 158 System.out.println(s); 159 } 160 } catch (Exception e) { 161 e.printStackTrace(); 162 } finally { 163 // 关闭资源 164 if (bufferedWriter != null) { 165 try { 166 bufferedWriter.close(); 167 } catch (IOException e) { 168 e.printStackTrace(); 169 } 170 } 171 if (bufferedReader != null) { 172 try { 173 bufferedReader.close(); 174 } catch (IOException e) { 175 e.printStackTrace(); 176 } 177 } 178 if (socket != null) { 179 try { 180 socket.close(); 181 } catch (IOException e) { 182 e.printStackTrace(); 183 } 184 } 185 } 186 } 187 }
三、运行结果