1、示例java
互联网的发展使得设备之间的网络通信必不可少,一般用的最多的传输层协议就是TCP协议。有以下场景:
有A、B两个节点,A、B创建TCP链接后,A对B说了一百句话。数据库
一、客户端程序编程
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(); } }
二、服务端程序网络
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(); } } }
三、运行结果
总读取次数老是少于100
2、问题
上面所述问题是很常见的场景,创建起一个长链接进行交互,列如RPC、NIO编程等等。
咱们但愿的结果是,一次交互一次读写,上面实例运行结果少于100次,说明有些数据库包被打包在一块儿发送,这就引出了今天的话题,TCP粘包拆包。
3、TCP粘包拆包
TCP协议是“流”协议,没有边界,TCP是传输层协议,它并不知道应用层业务数据的真正含义,它会根据TCP缓冲区的具体大小来进行包的划分,一个完整的包可能会被拆分红多个包来传输,也可能多个包会被合并层一个大数据包来传输,这就是粘包和拆包。
4、可能出现的状况
假设Client端向Server端发送A、B两个数据包,可能出现如下状况
一、服务端接收到A、B两个独立的数据包,没有拆包和粘包,这种状况是咱们大多数场景下但愿的;
二、服务端一次性收到了AB两个包,A、B两包被粘在一块儿发送过来;
三、A数据包被拆分红A一、A2,服务端先收到A1包,后收到A2和B的合包,这就发生了拆包和粘包两种状况;
四、状况最糟糕的是A、B两包被屡次拆分,发送到服务端。
大多数状况下,咱们但愿一次交互,能拿到交互中传递的完整信息,那么有哪些解决方案解决TCP传输过程当中的拆包与粘包问题呢?请关注《TCP粘包拆包二》。
socket
快乐源于分享。大数据
此博客乃做者原创, 转载请注明出处 code