粘包问题概述
1.1 描述背景
采用TCP协议进行网络数据传送的软件设计中,普遍存在粘包问题。这主要是由于现代操作系统的网络传输机制所产生的。我们知道,网络通信采用的套接字(socket)技术,其实现实际是由系统内核提供一片连续缓存(流缓冲)来实现应用层程序与网卡接口之间的中转功能。多个数据包被连续存储于连续的缓存中,在对数据包进行读取时由于无法确定发生方的发送边界,而采用某一估测值大小来进行数据读出,若双方的size不一致时就会使数据包的边界发生错位,导致读出错误的数据分包,进而曲解原始数据含义。
1.2 粘包的概念
粘包问题的本质就是数据读取边界错误所致,通过下图可以形象地理解其现象。
如图1所示,当前的socket缓存中已经有6个数据分组到达,其大小如图中数字。而应用程序在对数据进行收取时(如图2),采用了300字节的要求去读取,则会误将pkg1和pkg2一起收走当做一个包来处理。而实际上,很可能pkg1是一个文本文件的内容,而pkg2则可能是一个音频内容,这风马牛不相及的两个数据包却被揉进一个包进行处理,显然有失妥当。严重时可能因为丢了pkg2而导致软件陷入异常分支产生乌龙事件。
因此,粘包问题必须引起所有软件设计者(项目经理)的高度重视!
那么,或许会有读者发问,为何不让接收程序按照100字节来读取呢?我想如果您了解一些TCP编程的话就不会有这样的问题。网络通信程序中,数据包通常是不能确定大小的,尤其在软件设计阶段无法真的做到确定为一个固定值。比如聊天软件客户端若采用TCP传输一个用户名和密码到服务端进行验证登陆,我想这个数据包不过是几十字节,至多几百字节即可发送完毕,而有时候要传输一个很大的视频文件,即使分包发送也应该一个包在几千字节吧。(据说,某国电信平台的MW中见到过一次发送1.5万字节的电话数据)这种情况下,发送数据的分包大小无法固定,接收端也就无法固定。所以一般采用一个较为合理的预估值进行轮询接收。(网卡的MTU都是1500字节,因此这个预估值一般为MTU的1~3倍)。
粘包现象
说粘包之前,我们先说两个内容,1.缓冲区、2.windows下cmd窗口调用系统指令
9.1 缓冲区(下面粘包现象的图里面还有关于缓冲区的解释)
每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区。 write()/send() 并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送到目标机器。一旦将数据写入到缓冲区,函数就可以成功返回,不管它们有没有到达目标机器,也不管它们何时被发送到网络,这些都是TCP协议负责的事情。 TCP协议独立于 write()/send() 函数,数据有可能刚被写入缓冲区就发送到网络,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络,这取决于当时的网络情况、当前线程是否空闲等诸多因素,不由程序员控制。 read()/recv() 函数也是如此,也从输入缓冲区中读取数据,而不是直接从网络中读取。 这些I/O缓冲区特性可整理如下: 1.I/O缓冲区在每个TCP套接字中单独存在; 2.I/O缓冲区在创建套接字时自动生成; 3.即使关闭套接字也会继续传送输出缓冲区中遗留的数据; 4.关闭套接字将丢失输入缓冲区中的数据。 输入输出缓冲区的默认大小一般都是 8K,可以通过 getsockopt() 函数获取: 1.unsigned optVal; 2.int optLen = sizeof(int); 3.getsockopt(servSock, SOL_SOCKET, SO_SNDBUF,(char*)&optVal, &optLen); 4.printf("Buffer length: %d\n", optVal); socket缓冲区解释
9.2 windows下cmd窗口调用系统指令(linux下没有写出来,大家仿照windows的去摸索一下吧)
a.首先ctrl+r,弹出左下角的下图,输入cmd指令,确定
b.在打开的cmd窗口中输入dir(dir:查看当前文件夹下的所有文件和文件夹),你会看到下面的输出结果。
另外还有ipconfig(查看当前电脑的网络信息),在windows没有ls这个指令(ls在linux下是查看当前文件夹下所有文件和文件夹的指令,和windows下的dir是类似的),那么没有这个指令就会报下面这个错误
linux shell中一个运行多个命令,命令间用;隔开即可 windows的命令提示符中运行多条命令用的是:&&、||、& aa && bb 就是执行aa,成功后再执行bb aa || bb 先执行aa,若执行成功则不再执行bb,若失败则执行bb a & b 表示执行a再执行b,无论a是否成功 “执行成功”的意思是返回的errorlevel=0 windows下执行多条指令
windows下执行多条指令
原文地址:https://www.cnblogs.com/H1050676808/p/10226438.html