Socket 实现聊天功能

注:本文来自:简书: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 


image

原文地址:https://www.cnblogs.com/ios9/p/7473096.html