自定义Socket协议

服务器端

import java.io.DataInputStream;  
import java.io.EOFException;  
import java.io.IOException;  
import java.io.InputStream;  
import java.net.ServerSocket;  
import java.net.Socket;

public class MsgServer {  
    public static void main(String[] args) {
        try {
            MsgServer server = new MsgServer();
            server.setUpServer(8800);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void setUpServer(int port) throws IOException {
        ServerSocket server = new ServerSocket(port);
        while (true) {
            Socket client = server.accept();
            System.out.println("客户端IP:" + client.getRemoteSocketAddress());
            processMessage(client);
        }
    }

    private void processMessage(Socket client) throws IOException {
        InputStream ins = client.getInputStream();
        DataInputStream dins = new DataInputStream(ins);
        while (true) {
            byte flag;
            try {
                flag = dins.readByte();
            } catch (EOFException e) {
                break;
            }
            int totalLen = dins.readInt();
            System.out.println("接收消息类型:" + flag + ", 数据长度:" + totalLen);
            byte[] data = new byte[totalLen - 4 - 1];
            dins.readFully(data);
            String msg = new String(data);
            System.out.println("发来的内容是:" + msg);
        }
        dins.close();
        ins.close();
        System.out.println("close!!");
    }
}

客户端

import java.io.DataOutputStream;  
import java.io.IOException;  
import java.io.OutputStream;  
import java.net.Socket;  
import java.net.UnknownHostException;

public class MsgClient {

    public static void main(String[] args) {
        try {
            MsgClient client = new MsgClient();
            client.connServer("127.0.0.1", 8800);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private void sendTextMsg(DataOutputStream out, String msg) throws IOException {
        byte[] bytes = msg.getBytes();
        int totalLen = 1 + 4 + bytes.length;
        out.writeByte(1);
        out.writeInt(totalLen);
        out.write(bytes);
        out.flush();
    }

    public void connServer(String ip, int port) throws UnknownHostException, IOException {
        Socket client = new Socket(ip, port);
        OutputStream out = client.getOutputStream();
        DataOutputStream outs = new DataOutputStream(out);
        sendTextMsg(outs, "测试消息4");
        sendTextMsg(outs, "测试消息5");
        outs.close();
        client.close();
    }
}
  • socket在传输过程中,helloworld有可能被拆分了,分段到达客户端),例如 hello + world,一个分段就是一个包(Package),这个就是分包问题。
  • socket在传输过成功,不同时间发送的数据包有可能被合并,同时到达了客户端,这个就是黏包问题。例如发送方发送了hello+world,而接收方可能一次就接受了helloworld.
  • 为了解决分包、粘包问题,一般采用自定义协议: 包头+包体长度+包体

参考文档