还记得之前我写的一篇博客,说的是奇怪的在通信接收函数后调用Sleep函数,解决接收包冲突问题。今天终于得到正解了。

          我当时的分析是,程序执行太快,CPU还没有来的急执行写缓冲区操作。但事实是这样嘛?答案是是的。因为网络通信总是会有延时的。所以往往在处理大的数据时,会遇到数据缓冲区还没有被写,却被读取了。特别是当发送的数据包被TCP协议自动分包后,诡异的现象会发现很多很多。但是,真的诡异嘛?其实不然。

          TCP协议中一个协议包中存放的客户数据大小MTU大概为1512左右(具体记不清了)。这时候就需要自己装一个抓包工具来抓取。有时候自己设置的接收缓存在一个尴尬的数值时,比如1024。提醒一下,会发生一件让人很是郁闷的事情。

          比如发送的数据大小为4260。然后你用一个1024的buffer来接收,按照正常的思想,用4次接收4096个字节,然后再用一次接收164个字节,猛一看是这样的啊。但是如果在程序中,只是这样来考虑,会发现发生一个小概率的事件,是接收的数据总是缺少几个字节。那这缺少的几个字节到底跑哪里去了了。这时该怀疑是发送端没有发送完全(跟我的想法一样)。没有证据怎么能随便怀疑发送端了?

          于是,开始找证据,用抓包工具一抓,发现数据包是全的,但是那最后的几个字节居然单独被分解成包了。MTU的大小大概为1510左右,里面装的数据带该为1200左右,于是,最后的那几个字节的数据单独成包。当你按照想法,进行最后一次获取数据时,获取的是之前的数据,也就是没有包含最后一个数据包的数据。等最后一个数据到达缓冲区的时候,已经结束了获取过程。

一定要先知道要发送的数据大小,或是结束标志,根据大小或结束标志,循环判断,直到获取所有数据为止。如考虑会出现网络问题丢包等情况,可采取加定时判断等方式,超过计数或时间则把它干掉。


          大量数据传输,一定要记得分析TCP的数据分包。确保自己能准确的获取自己想要的所有数据。哦!之前说的那个添加Sleep函数其实是没必要的,只要设置循环判断数据条件,完全可以避免这个问题。