Socket 实现聊天功能

作者: jijs | 来源:发表于2017-08-14 22:43 被阅读715次

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

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

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

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

    服务端代码

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * @author jijs
     * @date 2017-08-14
     */
    public class ChatServer {
        public static void main(String[] args) throws Exception {
            start();
        }
    
        public static void start() throws Exception {
            try (ServerSocket ss = new ServerSocket(9000);
                    Socket s = ss.accept();
                    InputStream is = s.getInputStream();
                    OutputStream os = s.getOutputStream();) {
    
                //开启一个线程,实时读取对方发过来的消息
                new Thread(ChatUtil.receive(is)).start();
    
                //从控制台输入消息,并发送
                ChatUtil.send(os);
                
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
    }
    

    客户端代码

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    
    /**
     * @author jijs
     * @date 2017-08-14
     */
    public class ChatClient {
    
        public static void main(String[] args) throws Exception {
            start();
        }
    
        public static void start() {
            try (Socket s = new Socket("127.0.0.1", 9000);
                    InputStream is = s.getInputStream();
                    OutputStream os = s.getOutputStream();) {
    
                //开启一个线程,实时读取对方发过来的消息
                new Thread(ChatUtil.receive(is)).start();
    
                //从控制台输入消息,并发送
                ChatUtil.send(os);
    
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
    }
    

    聊天工具类

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.Scanner;
    
    /**
     * @author jijs
     * @date 2017-08-14
     */
    public class ChatUtil {
    
        /**
         * 读取对方发过来的消息
         * @param is
         * @return
         */
        public static Runnable receive(final InputStream is) {
            return new Runnable() {
                public void run() {
                    while (true) {
                        try {
                            // 当前消息总字节长度
                            int returnLen = ChatUtil.readLen(is);
                            byte[] b = new byte[returnLen];
                            int readSize = 0; // 每次读取的字节数
                            int count = 0; // 总读取的字节数
                            while (count < returnLen && (readSize = is.read(b)) != -1) {
                                count += readSize;
                            }
                            String str = new String(b, 0, readSize);
                            System.out.println("接收:" + str);
                        } catch (IOException e) {
                            e.printStackTrace();
                            break;
                        }
                    }
                }
            };
        }
    
        /**
         * 从控制台接收用户输入,发送消息给对方
         * @param os
         */
        public static void send(final OutputStream os) {
            Scanner scan = new Scanner(System.in);
            while (true) {
                try {
                    String s = scan.nextLine();
                    byte[] data = s.getBytes();
                    int len = data.length;
                    os.write(ChatUtil.int2byte(len));
                    os.write(data);
                    os.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                    break;
                }
            }
            scan.close();
        }
        
        /**
         * 读取消息长度
         * 消息格式为:消息长度+消息内容
         * @param is
         * @return
         * @throws IOException
         */
        public static int readLen(InputStream is) throws IOException {
            int b1 = is.read();
            int b2 = is.read();
            int b3 = is.read();
            int b4 = is.read();
            int len = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
            return len;
        }
        
        /**
         * int 转 byte[] 数组
         * @param len
         * @return
         */
        public static byte[] int2byte(int len) {
            byte[] b = new byte[4];
            b[0] = (byte) (len >> 24);
            b[1] = (byte) (len >> 16 & 0XFF);
            b[2] = (byte) (len >> 8 & 0XFF);
            b[3] = (byte) (len & 0XFF);
            return b;
        }
    }
    
    

    客户端控制台:


    客户端

    服务端控制台:


    服务端

    想了解更多精彩内容请关注我的公众号

    相关文章

      网友评论

        本文标题:Socket 实现聊天功能

        本文链接:https://www.haomeiwen.com/subject/apmprxtx.html