TCP粘包拆包一

一、示例

    互联网的发展使得设备之间的网络通讯必不可少,通常用的最多的传输层协议就是TCP协议。有如下场景:
    有A、B两个节点,A、B建立TCP连接后,A对B说了一百句话。

    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++) {
			os.write("A".getBytes());
		}
		pw.flush();
		pw.close();
		os.close();
		socket.close();
	}
}

   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[] b = new byte[10];
			while (is.read(b) != -1) {
				i++;
				System.out.println(new String(b));
				b = new byte[10];
			}
			System.out.println("总数读取次数" + i);
			is.close();
			socket.close();
		}
	}

}

3、运行结果
     总读取次数总是少于100

二、问题
    上面所述问题是很常见的场景,建立起一个长连接进行交互,列如RPC、NIO编程等等。
     我们希望的结果是,一次交互一次读写,上面实例运行结果少于100次,说明有些数据库包被打包在一起发送,这就引出了今天的话题,TCP粘包拆包。

三、TCP粘包拆包
    TCP协议是“流”协议,没有边界,TCP是传输层协议,它并不知道应用层业务数据的真正含义,它会根据TCP缓冲区的具体大小来进行包的划分,一个完整的包可能会被拆分成多个包来传输,也可能多个包会被合并层一个大数据包来传输,这就是粘包和拆包。

四、可能出现的情况
    假设Client端向Server端发送A、B两个数据包,可能出现以下情况
    1、服务端接收到A、B两个独立的数据包,没有拆包和粘包,这种情况是我们大多数场景下希望的;
    2、服务端一次性收到了AB两个包,A、B两包被粘在一起发送过来;
    3、A数据包被拆分成A1、A2,服务端先收到A1包,后收到A2和B的合包,这就发生了拆包和粘包两种情况;
    4、情况最糟糕的是A、B两包被多次拆分,发送到服务端。

    大多数情况下,我们希望一次交互,能拿到交互中传递的完整信息,那么有哪些解决方案解决TCP传输过程中的拆包与粘包问题呢?请关注《TCP粘包拆包二》。
 

快乐源于分享。

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

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