Socket 实现聊天功能

时间:2022-01-03 13:43:10

注:本文来自:简书:jianshu

作者:jijs
链接:http://www.jianshu.com/p/7c0722a8b66f
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


需要提前了解知识点
java.net.Socket 解析
java.net.ServerSocket 解析

使用socket实现一个端对端聊天系统。

消息的格式为:消息长度(int)+消息内容

通过消息长度来进行socket分包,防止读取出现半包、粘包等问题。

服务端代码

  1 import java.io.IOException;  2 import java.io.InputStream;
3 import java.io.OutputStream;
4 import java.net.ServerSocket;
5 import java.net.Socket;
6
7 /**
8 * @author jijs
9 * @date 2017-08-14
10 */

11 public class ChatServer {
12 public static void main(String[] args) throws Exception {
13 start();
14 }
15
16 public static void start() throws Exception {
17 try (ServerSocket ss = new ServerSocket(9000);
18 Socket s = ss.accept();
19 InputStream is = s.getInputStream();
20 OutputStream os = s.getOutputStream();) {
21
22 //开启一个线程,实时读取对方发过来的消息
23 new Thread(ChatUtil.receive(is)).start();
24
25 //从控制台输入消息,并发送
26 ChatUtil.send(os);
27
28 } catch (IOException e) {
29 e.printStackTrace();
30 }
31
32 }
33
34 }


客户端代码


  1 import java.io.IOException;  2 import java.io.InputStream;  3 import java.io.OutputStream;  4 import java.net.Socket;  5   6 /** 7  * @author jijs 8  * @date 2017-08-14 9  */ 10 public class ChatClient { 11  12     public static void main(String[] args) throws Exception { 13         start(); 14     } 15  16     public static void start() { 17         try (Socket s = new Socket("127.0.0.1", 9000); 18                 InputStream is = s.getInputStream(); 19                 OutputStream os = s.getOutputStream();) { 20  21             //开启一个线程,实时读取对方发过来的消息 22             new Thread(ChatUtil.receive(is)).start(); 23  24             //从控制台输入消息,并发送 25             ChatUtil.send(os); 26  27         } catch (IOException e) { 28             e.printStackTrace(); 29         } 30  31     } 32  33 }


聊天工具类

  1 import java.io.IOException;  2 import java.io.InputStream;  3 import java.io.OutputStream;  4 import java.util.Scanner;  5   6 /** 7  * @author jijs 8  * @date 2017-08-14 9  */ 10 public class ChatUtil { 11  12     /** 13      * 读取对方发过来的消息 14      * @param is 15      * @return 16      */ 17     public static Runnable receive(final InputStream is) { 18         return new Runnable() { 19             public void run() { 20                 while (true) { 21                     try { 22                         // 当前消息总字节长度 23                         int returnLen = ChatUtil.readLen(is); 24                         byte[] b = new byte[returnLen]; 25                         int readSize = 0; // 每次读取的字节数 26                         int count = 0; // 总读取的字节数 27                         while (count < returnLen && (readSize = is.read(b)) != -1) { 28                             count += readSize; 29                         } 30                         String str = new String(b, 0, readSize); 31                         System.out.println("接收:" + str); 32                     } catch (IOException e) { 33                         e.printStackTrace(); 34                         break; 35                     } 36                 } 37             } 38         }; 39     } 40  41     /** 42      * 从控制台接收用户输入,发送消息给对方 43      * @param os 44      */ 45     public static void send(final OutputStream os) { 46         Scanner scan = new Scanner(System.in); 47         while (true) { 48             try { 49                 String s = scan.nextLine(); 50                 byte[] data = s.getBytes(); 51                 int len = data.length; 52                 os.write(ChatUtil.int2byte(len)); 53                 os.write(data); 54                 os.flush(); 55             } catch (IOException e) { 56                 e.printStackTrace(); 57                 break; 58             } 59         } 60         scan.close(); 61     } 62  63     /** 64      * 读取消息长度 65      * 消息格式为:消息长度+消息内容 66      * @param is 67      * @return 68      * @throws IOException 69      */ 70     public static int readLen(InputStream is) throws IOException { 71         int b1 = is.read(); 72         int b2 = is.read(); 73         int b3 = is.read(); 74         int b4 = is.read(); 75         int len = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4; 76         return len; 77     } 78  79     /** 80      * int 转 byte[] 数组 81      * @param len 82      * @return 83      */ 84     public static byte[] int2byte(int len) { 85         byte[] b = new byte[4]; 86         b[0] = (byte) (len >> 24); 87         b[1] = (byte) (len >> 16 & 0XFF); 88         b[2] = (byte) (len >> 8 & 0XFF); 89         b[3] = (byte) (len & 0XFF); 90         return b; 91     } 92 } 93 


Socket 实现聊天功能