比如客户端要发送的数据是:"1234567890abcdefghij**********"             [客户端]
分成三个组包通过TCP发给iocp服务器,包发送顺序是:"包头1+123456789" "包头2+abcdefghij" "包头3+**********"[IOCP服务器]
我每个WSARecv的缓存接受长度是:包头加10个长 ,
要接受这组数据必须同时发送三个WSARecv并创建三个缓存顺序:缓存1,缓存2,缓存3问题一: (情况1)缓存1因其它原因数据未接受完,只收到"包头1+123" 还有"4567890"没收到,需要继续接受.
       这个时候,缓存2会不会把剩下"4567890"接受完并且还能接受一部分包头2的的数据?问题二:(情况2)缓存1接受的是包头3的数据,缓存2接受的是包头1的数据,缓存3接受包头2数据. 这种情况会发生嘛?
       (当然这种情况可根据包头判断顺序)问题三:一般造成缓存未接受完指定长度数据是什么原因造成的呢?如果哪里不对,也可以发表你自己的看法

解决方案 »

  1.   

    你这么短的数据不会引起二三四层重新分包的,所以不会乱的,若是打包后超出了TCP包的长度才存在拆包的可能。在CSMA/CD中,一接是一个包的,当然这个是指底层的包的。
      

  2.   

    问题一:有可能,但也可能缓存2没能完整地接收到10个字节的长度,而又是一部分。它的机制就是这样,实际接收长度 <= 缓存大小。问题二:这里你描述不太清楚,是包头没对上包体吗?还是说缓存1没有收到包1,顺序乱了?
    如果是前一种,这种情况不会发生,head与body不会错乱,TCP本身是保序的。
    如果是后一种,那是有可能的,IOCP是排队的,就看哪个WSARecv请求先入队,先入队的先收数据,在多线程的情况下,系统机制很难保证你不错序,只能靠你自己重新排序。特别是,一般等待完成通知都是多个线程同时等,即使一先一后等来了两个完成通知,你也难以判断到底是哪个通知先到的,都是多线程的问题啦。问题三:这个就很复杂了,不是完成端口的问题,而是TCP协议栈和物理网络问题了,总之记住一点,TCP系统协议栈只能保证数据像流水一样被发送接收,作为接收端你不应该去猜度发送端的片段大小。
      

  3.   

    前两个问题楼上的已经回答了。
    第三个问题,TCP是面向“流”的,不是面向“包”的,不是你调用一次send,TCP协议栈就得发一个包出去的。你调用send发送的数据,在TCP协议栈中被合并为一个整体的数据块,在合适的时候取出一段封装为1个TCP数据包进行发送,取出的这一段长度和你调用send加入的长度是完全没有联系的,接收端收到一个TCP数据包就通知上层了
      

  4.   

    数据少不会乱,一个就接完了。数据多了不控制好协议也会乱!
    但关键是IOCP模型里一般没有这么干的!不会在没收到数据前一次性发出很多WSAAccept,在IOCP模型下,发出多个WSAAccept的情况一般是:
    包头指定数据包大小,收到客户端数据后,如果数据大于buffer,就计算需要几个Accept去接收,然后才会发送多个WSAAccept去接收,因为数据已经收到了,数据肯定是按顺序接收的。
      

  5.   

    我的看法是:
    问题一:对于发送方的每个send动作,接收方的套接字都会向程序发送通知,而且是如果接收方的接收缓存如果没满,则只会发送一个通知,但如果发送的数据量大,超过了缓存大小,则会发送多次通知.因为你的缓存是刚好够大,所以你不可能只收到一个包的一部份内容.
    问题二:有可能, 其实我们网络基础里讲的TCP数据各个分组可能会起不同路径,先发的可能后到,而后发的可能先到,我认为这只是对一个send动作所发送的数据内部来说的,接收方的套接字会把一次对方send 的数据组装好后才向上通知,你这里所提的问题不属于这种情况. 你的情况是是否先send的后收到,而后send的是否先收到,这是有可能的,这要看网络底层的通信情况,但一般情况是不会发生的,因为网络是相对稳定的.
    问题三:这个我不太确定,谈谈看法:正常情况下应该会接收完指定长度的.如果真的出现你所说的情况,可能某个数据分组在网络中传送时出错或丢失,本来是应该会自动通知发送方的TCP重发的,但此时发送方的机器可能关机或程序已强行退出,根本没机会重发了.
      

  6.   

    为每一个连接建立一个独立的buffer接受数据就应该不会乱了,不会需要排队了