TCP粘包拆包二

一、TCP粘包拆包问题解决方案
    《TCP粘包拆包一》抛出了粘包拆包的问题,那么有哪些解决方案呢?
    常用解决方案:
    1、固定消息长度,例如每个报文长度500字节,不够该长度的用特殊字符补齐,如空格、\001等,这种       方式会增加一些无用字符的传递,浪费网络流量。
    2、包尾部追加特殊符号进行分割,这种方式如果传输的数据中有分割符号,还要进行转义,增加编码的     难度。
    3、消息分为消息头和消息体两部分;
    4、开发复杂应用协议,如HTTP协议等

二、示例
    我们实现第三种方案来解决粘包拆包问题, 一个报文分两块,消息头我们用4个字节来存储消息实体的字节数,编码实现如下:
1、客户端代码

public class SocketClient {
	public static void main(String[] args) throws Exception {
		Socket socket = new Socket("127.0.0.1", 8088);
		OutputStream os = socket.getOutputStream();
		PrintWriter pw = new PrintWriter(os);
		for (int i = 0; i < 100; i++) {
			byte[] head = intToBytes("A".getBytes().length);
			// 消息实体的长度是用消息头和消息体组成
			byte[] message = new byte[head.length + "A".getBytes().length];
			System.arraycopy(head, 0, message, 0, head.length);
			System.arraycopy("A".getBytes(), 0, message, head.length, "A".getBytes().length);
			os.write(message);
		}
		pw.flush();
		pw.close();
		os.close();
		socket.close();
	}

	// int型转字节数组,java里int用4字节表示,所以返回的字节数组长度为4
	public static byte[] intToBytes(int value) {
		byte[] src = new byte[4];
		src[0] = (byte) ((value >> 24) & 0xFF);
		src[1] = (byte) ((value >> 16) & 0xFF);
		src[2] = (byte) ((value >> 8) & 0xFF);
		src[3] = (byte) (value & 0xFF);
		return src;
	}
}

2、服务端代码

public class SocketServer {
	public static void main(String[] args) throws Exception {
		ServerSocket serverSocket = new ServerSocket(8088);
		while (true) {
			Socket socket = serverSocket.accept();
			InputStream is = socket.getInputStream();
			int i = 0;
			byte[] head = new byte[4];// 先读取4个字节消息头
			while (is.read(head) != -1) {
				i++;
				int messageLenth = byteArrayToInt(head);
				byte message[] = new byte[messageLenth];
				is.read(message);// 读取消息体
				System.out.println(new String(message));
			}
			System.out.println("总数读取次数" + i);
			is.close();
			socket.close();
		}
	}

	public static int byteArrayToInt(byte[] b) {
		return b[3] & 0xFF | (b[2] & 0xFF) << 8 | (b[1] & 0xFF) << 16 | (b[0] & 0xFF) << 24;
	}
}

 3、运行结果

TCP粘包拆包二_第1张图片
     这样就实现一个报文一个报文的读取了,基于这种实现也可以解决RPC框架中的粘包拆包问题。

三、问题
    Java支持更高效的IO方式Nio,那么也有一些高效Nio框架,如netty、mina,这些框架极大的提高了程序员网络编程的效率,那么这些框架提供哪些方法去解决拆包粘包问题呢? 
 

快乐源于分享。

   此博客乃作者原创, 转载请注明出处   

你可能感兴趣的:(TCP粘包拆包二)