IOCP发送数据的小问题?

zjfhgdx 2011-09-07 08:16:12
请问对同一个socket连续调用两次wsasend,能不能保证这两次数据的发送顺序?
也就是说,是不是等第一次的数据全部发送完后才会发送第二次调用wsasend时的数据?

会不会出现,发关第一次的数据一半,然后又发送第二次的数据,然后再发送第一次的.......

请教,谢谢.
...全文
226 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
xxq123321 2011-09-09
  • 打赏
  • 举报
回复
另外对与同一个socket连续调用两次wsasend,能不能保证这两次数据的发送顺序的问题,个人认为
1.既然wsasend是异步的,通用的做法自然是等待本次异步操作完成情况,然后进行下一次投递,
2.对于不等待wsasend异步完成就再次发送的操作(比如说在一个循环中调用wsasend)个人认为是不正确的编码方式,即你在不知道网络数据是否成功发送的基础上(套接字或其它网络环境异常)调用下一次wsasend。
3.对多次连续调用wsasend,要弄清楚系统是每次将发送数据投递到系统发送缓冲的末尾,还是直接覆盖原来缓冲,如果是前者,那系统是否有足够缓冲来应对循环调用wsasend产生的大量发送数据,如果为后者,显然多次连续调用wsasend就是明显错误的,这个楼主可以自己测试一下
zjfhgdx 2011-09-09
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 xxq123321 的回复:]

对2楼接收数据会乱序的说法有点不同意见:
IOCP既然作为一个高性能的网络模型,显然不会吧tcp这种在网络层已经解决过的网络乱序问题再交给应用层再次重新处理,如果使用tcp协议的iocp模型时出现需要自己代码处理网络包乱序的问题,我觉得多半是代码本身的问题而不是iocp的问题,我的理解是这样的,在多线程的iocp接收中:
1.服务器把客户端socket关联iocp队列,在某个线程调用wsar……
[/Quote]
我的模型也是这样的.谢谢,你的回答.
xxq123321 2011-09-08
  • 打赏
  • 举报
回复
对2楼接收数据会乱序的说法有点不同意见:
IOCP既然作为一个高性能的网络模型,显然不会吧tcp这种在网络层已经解决过的网络乱序问题再交给应用层再次重新处理,如果使用tcp协议的iocp模型时出现需要自己代码处理网络包乱序的问题,我觉得多半是代码本身的问题而不是iocp的问题,我的理解是这样的,在多线程的iocp接收中:
1.服务器把客户端socket关联iocp队列,在某个线程调用wsarecv对客户端套接字投递第一次接收
2.服务去在多线程中调用GetQueuedCompletionStatus等待客户端数据到来
3.客户端发送数据给服务器
4.服务器的系统缓存中接收到数据,不管是否接收完成,GetQueuedCompletionStatus返回数据给应用层
5.这就是我和2楼不同意见的地方,GetQueuedCompletionStatus在某一个线程返回后,该线程对接收到的数据做出处理,除非此时另外有线程或其它地方对同一客户端调用wsarecv,否则不是此时是否客户端有新的发送数据上来,GetQueuedCompletionStatus都不会再次返回该客户端socket的数据,即一次wsarecv操作,只会导致一个GetQueuedCompletionStatus返回(不管是否接收到所有客户端send数据)。
6.一般情况下,线程处理完数据,再次调用wsarecv投递新的接收情况,导致下次GetQueuedCompletionStatus返回数据.

以上是我编程中采用的iocp模型处理方式,和2楼的主要不同观点是,我认为同时在多个线程中对同一个socket调用recv或其他操作引发的网络乱序或其它不可预知的问题是应用层编码本身的问题,而不是iocp的问题
zjfhgdx 2011-09-07
  • 打赏
  • 举报
回复
谢谢,LS大大们的回答让有对这个有了更加清晰的理解.

我的确实是多线程的.
不过我是对每个socket每接收并处理完一次数据后,才调用WSARecv的.
这样应该可以保证这个socket数据的顺序吧?也应该可能保证这个socket同时只被一个线程处理吧?
因为在一次数据处理完之前不调用WSARecv,这样也就不会接收到第二次数据了对吧??.
shenyi0106 2011-09-07
  • 打赏
  • 举报
回复
备注:
以上说明仅仅适用于TCP协议,UDP协议不适用
shenyi0106 2011-09-07
  • 打赏
  • 举报
回复
简单的说就是:对同一个socket的发送缓冲区,多线程是互斥使用的,任何要发送数据的线程,必须等待发送缓冲区中数据发送完毕,才能将自己的数据拷贝进去,否则将等待,直到原数据发送完成
shenyi0106 2011-09-07
  • 打赏
  • 举报
回复
不存你说的这个情况,不管是不是多线程的
可以看看MSDN上对send函数的REMARK,其中有一段是这么说的:
在调用send函数发送前,先检查发送缓冲区是否有数据正在发送,如果有,则等待发送完;
如果没有,则拷贝当前的数据到发送缓冲区,并返回拷贝的数量
lijianli9 2011-09-07
  • 打赏
  • 举报
回复
ls说很清楚了。关键看是否在多线程中对同一个socket进行操作。
如果操作了,就要在发送端带上包序号,然后在接收端进行组包。

jackson35296 2011-09-07
  • 打赏
  • 举报
回复
同一线程中连续调用两次WSASend是可以保证发送顺序的

会不会出现,发关第一次的数据一半,然后又发送第二次的数据,然后再发送第一次的.......
发送的时候不会的,TCP/IP协议保证按顺序发送两次的数据

IOCP的乱序主要发生在接收端多线程接收同一套接字的数据问题。
假如接收端有A,B,C,D共4个线程去接收这两次的数据。A线程可能接收到第一次的一半,B线程接收到第一次的另一半,C线程接收到第二次的一半,D线程接收到第二次的另一半。操作系统底层是遵守TCP/IP协议按顺序接收两次的数据,但投递到应用层之后,由于是多线程接收,就存在线程的优先级问题。在拼合这4个线程接收到的数据的时候就可能出现拼合顺序错误,就是所谓的IOCP socket乱序问题。

A线程首先接收数据这个没有问题,但是把数据投递到队列中进行拼接的时候,如果突然卡了一下(CPU刚好在给B线程分配时间片或者B线程优先级高于A线程),导致B线程后接收,但是先投递了数据。这样就导致第一次的数据拼接顺序错误。

根本原因就在于线程间时间片的切换和线程优先级不受控。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧