快捷搜索:  汽车  科技

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)在 run() 方法中,创建字节数组来接收客户端发送的数据流。定义字节数组时, byte[] by = new byte[1024 2]; 这里 2的原因是,为了区分发送的用户以及传输的数据类型是消息文本还是文件。其中,第一位标志位用来表示用户的id,第二位标志位用1,2来表示发送的是消息还是文件,1表示发送的是消息,2表示发送的是文件。 下面客户端代码时可以更好理解。<pre class="prettyprint hljs cs" style="padding: 0.5em; font-family: Menlo Monaco Consolas "Courier New" monospace; color: rgb(68 68 68); border-radius: 4px; display: block; margin: 0px

java socket实现简易多人聊天室传输聊天内容或文件

Java小练手项目:用Java Socket实现多人聊天室,聊天室功能包括传输聊天内容或者文件。相比于其它的聊天室,增加了传输文件的功能供参考。

模块拆解

分成服务端和客户端两部分来写

服务端包括监听线程和处理收发信线程:

  1. 创建监听线程,监听客户端的连接。将每个连接的客户端加入维护的列表,并为每个连接的客户端开启一个处理收发信的线程。
  2. 在每个客户端的收发信线程中,接收每个客户端发回的消息,并对其进行转发到相应接收的客户端上,以此实现多人聊天室。
  3. 添加处理传输文件的判断,通过在传输的字节数组中添加标志位来区分传输的是文本消息,还是文件。

客户端包括发送消息线程和接收消息线程:

  1. 发送消息线程,用来处理用户的输入信息,判断输入的是文本信息还是文件,并修改传输的字节数组标志位进行区分。最后将信息传输给服务器。
  2. 接收消息线程,用来处理服务器发回的信息,根据标志位判断输入的是文本信息还是文件,并做相应处理。如果是文本信息,则显示在控制台,如果是文件,则保存在指定目录下。

项目的目录结构如下所示

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)(1)

接下来,给出实际的代码进行分析

项目代码服务器端监听线程

<pre class="prettyprint hljs gradle" style="padding: 0.5em; font-family: Menlo Monaco Consolas "Courier New" monospace; color: rgb(68 68 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246 246 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package Server; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; public class MultiServer { public static void main(String[] args) { ServerSocket ss = null; Socket s = null; // 定义一个List列表来保存每个客户端,每新建一个客户端连接,就添加到List列表里。 List<Socket> listSocket = new ArrayList<>(); try { // 1\. 创建ServerSocket类型的对象并提供端口号 ss = new ServerSocket(9999); // 2\. 等待客户端的连接请求,调用accept方法 // 采用多线程的方式,允许多个用户请求连接。 int i = 0; while (true) { System.out.println("等待客户端的连接请求..."); s = ss.accept(); listSocket.add(s); //sArr[i] = s; i ; System.out.printf("欢迎用户%d加入群聊!\n" i); System.out.printf("目前群聊中共有%d人\n" listSocket.size()); InetAddress inetAddress = s.getInetAddress(); System.out.println("客户端" inetAddress "连接成功!"); // 调用多线程方法,每一个连上的客户端,服务器都有一个线程为之服务 new MultiServerThread(s inetAddress listSocket).start(); } } catch (IOException e) { e.printStackTrace(); } finally { // 关闭流 try { ss.close(); } catch (IOException e) { e.printStackTrace(); } try { s.close(); } catch (IOException e) { e.printStackTrace(); } } } }

上述代码实现服务器监听客户端连接,利用 accept 方法,每加入一个客户端,服务器都创建一个线程为之服务,同时将其加入一个List集合中,用来保存已加入聊天室的所有客户端。

处理收发信的线程

<pre class="prettyprint hljs cs" style="padding: 0.5em; font-family: Menlo Monaco Consolas "Courier New" monospace; color: rgb(68 68 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246 246 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package Server; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.util.Arrays; import java.util.List; public class MultiServerThread extends Thread { private Socket s; private InetAddress inetAddress; private List<Socket> listSockets; public MultiServerThread(Socket s InetAddress inetAddress List<Socket> listSockets) { this.s = s; this.inetAddress = inetAddress; this.listSockets = listSockets; } public void BroadCast(Socket s byte[] by int res) { // 将服务器接收到的消息发送给除了发送方以外的其他客户端 int i = 0; for (Socket socket: listSockets) { if (s!=socket) // 判断不是当前发送的客户端 { System.out.println("发送给用户: " listSockets.indexOf(socket)); BufferedOutputStream ps = null; try { ps = new BufferedOutputStream(socket.getOutputStream()); ps.write(by 0 res); // 写入输出流,将内容发送给客户端的输入流 ps.flush(); } catch (IOException e) { e.printStackTrace(); } } } } // 服务器与客户端的交互线程 @Override public void run() { BufferedInputStream ois = null; BufferedOutputStream oos = null; try { ois = new BufferedInputStream(s.getInputStream()); oos = new BufferedOutputStream(s.getOutputStream()); int i = 0; while (true) { //System.out.println("进入MultiChatServerThread"); byte[] by = new byte[1024 2]; //System.out.println("by.length: " by.length); int res = 0; res = ois.read(by); // 对读取到的字节数组第一位位置进行修改,标识该数据流是由哪个用户发送来的 by[0] = (byte)listSockets.indexOf(s); if (by[1] == 2){ // 因为前两个位置是标志位,所以length的大小为读取的字节数-2 同时offset也从第三个位置(下标是2)开始读 String receive = new String(by 2 res-2); if (receive.equalsIgnoreCase("bye")) { // 如果客户端发送的是bye 说明其下线,则从listSockets里删除对应的socket. oos.write(receive.getBytes()); // 把bye给客户端的读取线程,从而可以关闭掉读取线程 oos.flush(); System.out.printf("用户%d下线 " listSockets.indexOf(s)); listSockets.remove(s); System.out.printf("目前聊天室仍有%d人\n" listSockets.size()); } } System.out.println("i" i "res = " res); System.out.println("by.length: " by.length); System.out.println("Socket[]: " Arrays.toString(listSockets.toArray())); // 调用函数,将接受到的消息发送给所有客户端 BroadCast(s by res); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (oos != null) { oos.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (ois != null) { ois.close(); } } catch (IOException e) { e.printStackTrace(); } } } }

在处理收发信的线程中,利用 BroadCast() 方法将服务器接收到的消息发送给除了发送方以外的其他客户端。

在 run() 方法中,创建字节数组来接收客户端发送的数据流。定义字节数组时, byte[] by = new byte[1024 2]; 这里 2的原因是,为了区分发送的用户以及传输的数据类型是消息文本还是文件。其中,第一位标志位用来表示用户的id,第二位标志位用1,2来表示发送的是消息还是文件,1表示发送的是消息,2表示发送的是文件。 下面客户端代码时可以更好理解。

判断用户下线的标志是用户发送 bye ,说明其下线,则服务端从listSockets里删除对应的socket。同时,将把 bye 发送给客户端的读取线程,提示其可以关闭掉读取线程。

以上就是服务端的实现逻辑。整体思路就是:
  1. 首先创建监听线程,接收每个客户端的连接请求,并创建一个List集合保存。
  2. 创建一个处理收发信的线程,即每个客户端发送的聊天内容,都先统一发回给服务器端,再由服务器端进行集中转发给每个客户端。
客户端

客户端的两个线程包括发送消息给服务器和读取服务器发送的消息,用主线程和子线程来分别实现。

客户端1

<pre class="prettyprint hljs cs" style="padding: 0.5em; font-family: Menlo Monaco Consolas "Courier New" monospace; color: rgb(68 68 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246 246 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package Client; import java.io.*; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; public class MultiClient extends Thread { private Socket ss; public MultiClient() { } public MultiClient(Socket ss) { this.ss = ss; } public byte[] reviseArr(byte[] by int res) { byte[] newByteArr = new byte[by.length 2]; // 将by字节数组的内容都往后移动两位,即头部的两个位置空出来作为标志位 for (int i = 0; i < by.length; i ) { newByteArr[i 2] = by[i]; } return newByteArr; } // 子线程执行读操作,读取服务端发回的数据 @Override public void run() { BufferedInputStream bis = null; BufferedOutputStream bosFile = null; // 与输出文件流相关联 try { bis = new BufferedInputStream(ss.getInputStream()); //bosFile = new BufferedOutputStream(new FileOutputStream("./directoryTest/src/用户1 IO流的框架图.png")); // 等待接收服务器发送回来的消息 while(true) { byte[] by = new byte[1024 2]; int res = bis.read(by); int sendUser = by[0]; Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss"); String format = sdf.format(date); if (by[1] == 1) // 说明传的是文件 { //String filePath = String.format("./directoryTest/src/用户%d传送来的IO流的框架图.png" sendUser); bosFile = new BufferedOutputStream(new FileOutputStream("./directoryTest/用户" sendUser "-传输的文件.png" true)); bosFile.write(by 2 res-2); bosFile.flush(); if (res<1026) // 说明是最后一次在传送文件,所以传送的字节数才会小于字节数组by的大小 { System.out.println("用户" sendUser "\t" format ":"); System.out.printf("用户%d发送的文件传输完成\n" sendUser); } } else // 说明传输的是聊天内容,则按字符串的形式进行解析 { // 利用String构造方法的形式,将字节数组转化成字符串打印出来 String receive = new String(by 2 res); System.out.println("用户" sendUser "\t" format ":"); System.out.println(receive); } } } catch (IOException e) { e.printStackTrace(); }finally{ try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { // 主线程执行写操作,发送消息到服务器 Socket ss = null; BufferedOutputStream bos = null; BufferedInputStream bis = null; // 与文件关联的流 MultiClient mcc = null; try { ss = new Socket("127.0.0.1" 9999); System.out.println("服务器连接成功"); System.out.println("-----------聊天室-----------"); bos = new BufferedOutputStream(ss.getOutputStream()); Scanner sc = new Scanner(System.in); mcc = new MultiClient(ss); mcc.start(); byte[] by = new byte[1024]; int res = 0; int i = 0; while(true) { // 由用户输入选择执行不同的传输任务 // 若用户输入传输文件,则传输指定文件,否则,则正常聊天任务 String str = sc.nextLine(); if (str.equals("传输文件")) { bis = new BufferedInputStream(new FileInputStream("./directoryTest/壁纸1.png")); while ((res = bis.read(by)) != -1) { //System.out.println("i" i " res: " res); byte[] newByteArr = mcc.reviseArr(by res);; newByteArr[1] = 1; // 表示第二个位置上的值为1时表示传输的是文件 bos.write(newByteArr 0 res 2); bos.flush(); } } else{ byte[] sb = str.getBytes(); // 转化为字节数组 byte[] newByteArr = mcc.reviseArr(sb sb.length); newByteArr[1] = 2; // 表示第二个位置上的值为2时表示传输的是聊天内容 bos.write(newByteArr); // 把内容发给服务器 bos.flush(); if (str.equalsIgnoreCase("bye")) { System.out.println("用户下线!"); break; } } } }catch (IOException e) { e.printStackTrace(); }finally { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } try { mcc.stop(); ss.close(); } catch (IOException e) { e.printStackTrace(); } } } }

在客户端实现中,主线程执行写操作,发送消息到服务器,接收键盘的标准输入。在主线程发送消息时,判断用户的输入,如果输入的文本内容是传输文件,则会去读取指定路径下的文件,并利用 BufferedOutputStream 方法将文件转化为字节缓冲输出流发送。

这里 reviseArr 方法,是将读入文件输入流的102大小的字节数组往后移动两位,实现前两位作为标志位,区分用户id和传输数据类型的目的。如果传输的是文件,会在第二个标志位赋1,如果传输的是消息文本,则第二个标志位赋2。

若用户发送的消息是"bye",则表示用户下线,利用 break 跳出主线程循环,并在 finally 中调用 mcc.stop() 关闭子线程,从而关闭该客户端。

在子线程中,若用户发送的是文件,则利用字节缓冲输入流 BufferedInputStream 将文件写入到指定路径中,并在文件名中简易标识发送用户。若接收的字节数组长度小于设定的1026,说明是最后一次在传送文件,在将最后一次文件的输入流写入后,在控制台打印文件传输完成的提示信息。

以上是客户端1的实现代码,其它客户端的实现代码类似

客户端2

<pre class="prettyprint hljs cs" style="padding: 0.5em; font-family: Menlo Monaco Consolas "Courier New" monospace; color: rgb(68 68 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246 246 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package Client; import java.io.*; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; public class MultiClient2 extends Thread { private Socket ss; public MultiClient2() { } public MultiClient2(Socket ss) { this.ss = ss; } public byte[] reviseArr(byte[] by int res) { byte[] newByteArr = new byte[by.length 2]; // 将by字节数组的内容都往后移动两位,即头部的两个位置空出来作为标志位 for (int i = 0; i < by.length; i ) { newByteArr[i 2] = by[i]; } return newByteArr; } @Override public void run() { BufferedInputStream bis = null; BufferedOutputStream bosFile = null; // 与输出文件流相关联 try { bis = new BufferedInputStream(ss.getInputStream()); // 等待接收服务器发送回来的消息 while(true) { byte[] by = new byte[1024 2]; int res = bis.read(by); int sendUser = by[0]; Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss"); String format = sdf.format(date); if (by[1] == 1) // 说明传的是文件 { //String filePath = String.format("./directoryTest/src/用户%d传送来的IO流的框架图.png" sendUser); bosFile = new BufferedOutputStream(new FileOutputStream("./directoryTest/用户" sendUser "-传输的文件.png" true)); bosFile.write(by 2 res-2); bosFile.flush(); if (res<1026) // 说明是最后一次在传送文件,所以传送的字节数才会小于字节数组by的大小 { System.out.println("用户" sendUser "\t" format ":"); System.out.printf("用户%d发送的文件传输完成\n" sendUser); } } else // 说明传输的是聊天内容,则按字符串的形式进行解析 { // 利用String构造方法的形式,将字节数组转化成字符串打印出来 String receive = new String(by 2 res); System.out.println("用户" sendUser "\t" format ":"); System.out.println(receive); } } } catch (IOException e) { e.printStackTrace(); }finally{ try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { // 主线程写操作 Socket ss = null; BufferedOutputStream bos = null; BufferedInputStream bis = null; // 与文件关联的流 MultiClient2 mcc = null; try { ss = new Socket("127.0.0.1" 9999); System.out.println("服务器连接成功"); System.out.println("-----------聊天室-----------"); bos = new BufferedOutputStream(ss.getOutputStream()); Scanner sc = new Scanner(System.in); mcc = new MultiClient2(ss); mcc.start(); byte[] by = new byte[1024]; int res = 0; int i = 0; while(true) { String str = sc.nextLine(); if (str.equals("传输文件")) { bis = new BufferedInputStream(new FileInputStream("./directoryTest/壁纸1.png")); while ((res = bis.read(by)) != -1) { i = 1; //System.out.println("i" i " res: " res); byte[] newByteArr = mcc.reviseArr(by res);; newByteArr[1] = 1; // 表示第二个位置上的值为1时表示传输的是文件 bos.write(newByteArr 0 res 2); bos.flush(); } } else{ byte[] sb = str.getBytes(); // 转化为字节数组 byte[] newByteArr = mcc.reviseArr(sb sb.length); //System.out.println("newByteArr: " Arrays.toString(newByteArr)); newByteArr[1] = 2; // 表示第二个位置上的值为2时表示传输的是聊天内容 bos.write(newByteArr); // 把内容发给服务器 bos.flush(); if (str.equalsIgnoreCase("bye")) { System.out.println("用户下线!"); break; } } } }catch (IOException e) { e.printStackTrace(); }finally { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } try { mcc.stop(); ss.close(); } catch (IOException e) { e.printStackTrace(); } } } } 客户端3

<pre class="prettyprint hljs cs" style="padding: 0.5em; font-family: Menlo Monaco Consolas "Courier New" monospace; color: rgb(68 68 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246 246 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package Client; import java.io.*; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; public class MultiClient3 extends Thread { private Socket ss; public MultiClient3() { } public MultiClient3(Socket ss) { this.ss = ss; } public byte[] reviseArr(byte[] by int res) { byte[] newByteArr = new byte[by.length 2]; // 将by字节数组的内容都往后移动两位,即头部的两个位置空出来作为标志位 for (int i = 0; i < by.length; i ) { newByteArr[i 2] = by[i]; } return newByteArr; } @Override public void run() { BufferedInputStream bis = null; BufferedOutputStream bosFile = null; // 与输出文件流相关联 try { bis = new BufferedInputStream(ss.getInputStream()); // 等待接收服务器发送回来的消息 while(true) { byte[] by = new byte[1024 2]; int res = bis.read(by); int sendUser = by[0]; Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss"); String format = sdf.format(date); if (by[1] == 1) // 说明传的是文件 { bosFile = new BufferedOutputStream(new FileOutputStream("./directoryTest/用户" sendUser "-传输的文件.png" true)); bosFile.write(by 2 res-2); bosFile.flush(); if (res<1026) // 说明是最后一次在传送文件,所以传送的字节数才会小于字节数组by的大小 { //System.out.println("客户端接收到的信息" receive); System.out.println("用户" sendUser "\t" format ":"); System.out.printf("用户%d发送的文件传输完成\n" sendUser); } } else // 说明传输的是聊天内容,则按字符串的形式进行解析 { // 利用String构造方法的形式,将字节数组转化成字符串打印出来 String receive = new String(by 2 res); System.out.println("用户" sendUser "\t" format ":"); System.out.println(receive); } } } catch (IOException e) { e.printStackTrace(); }finally{ try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { // 主线程写操作 //MultiClient mc = new MultiClient(); Socket ss = null; BufferedOutputStream bos = null; BufferedInputStream bis = null; // 与文件关联的流 MultiClient3 mcc = null; try { ss = new Socket("127.0.0.1" 9999); System.out.println("服务器连接成功"); System.out.println("-----------聊天室-----------"); bos = new BufferedOutputStream(ss.getOutputStream()); Scanner sc = new Scanner(System.in); mcc = new MultiClient3(ss); mcc.start(); byte[] by = new byte[1024]; int res = 0; int i = 0; while(true) { String str = sc.nextLine(); if (str.equals("传输文件")) { bis = new BufferedInputStream(new FileInputStream("./directoryTest/壁纸1.png")); while ((res = bis.read(by)) != -1) { byte[] newByteArr = mcc.reviseArr(by res);; newByteArr[1] = 1; // 表示第二个位置上的值为1时表示传输的是文件 bos.write(newByteArr 0 res 2); bos.flush(); } } else{ byte[] sb = str.getBytes(); // 转化为字节数组 byte[] newByteArr = mcc.reviseArr(sb sb.length); newByteArr[1] = 2; // 表示第二个位置上的值为2时表示传输的是聊天内容 bos.write(newByteArr); // 把内容发给服务器 bos.flush(); // 如果用户输入bye则表示用户下线 if (str.equalsIgnoreCase("bye")) { System.out.println("用户下线!"); break; } } } }catch (IOException e) { e.printStackTrace(); }finally { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } try { mcc.stop(); ss.close(); } catch (IOException e) { e.printStackTrace(); } } } } 功能展示

开启服务器和3个客户端,初始状态

聊天室

每有一个客户端连接,会打印相应的提示信息

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)(2)

三个客户端连接成功,打印提示信息

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)(3)

接下来,进行聊天功能的展示

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)(4)

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)(5)

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)(6)

可以看到,聊天室里标识出每个用户以及发送的时间和消息,可以实现基本的聊天功能。

传输文件

在客户端1输入传输文件

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)(7)

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)(8)

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)(9)

进入到写入的目录下,存在相应的文件:

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)(10)

即实现了聊天室和传输文件的功能,最后客户端1发送 bye ,该客户端断开连接

javasocket实现简易聊天室的思路(Socket实现简易多人聊天室传输聊天内容或文件)(11)

<pre class="hljs" style="padding: 0.5em; font-family: Menlo Monaco

猜您喜欢: