(问题是从msdn论坛复制的)

MSDN这样说:


  如果您使用的是I / O完成端口,请注意
  对WSASend的调用也是缓冲区被分配的顺序
  填充。不应在同一套接字上调用WSASend
  同时来自不同的线程,因为这可能会导致
  不可预测的缓冲区顺序。


好的...但是如果我不在乎此订单,也不在乎该订单,我会在另一侧收到它...那么我可以使用它吗?从多个线程调用WSASend是否安全?以及包裹将按照我如何通过的方式交付(也许订购方式有所不同,但是完整)?

例如。 ->我发送[12a],[34b],[11c]和[223d] ...([]标记了我在一次呼叫中传递给WSASend的单位),例如34b,11c,12a,223d?还是会崩溃?还是我可以收到2a,34b,7a,5c等...

因此,也许问题应该是->线程安全吗?它是原子的吗? (我说的是与IOCP一起使用的WSASend,所以重叠)

最佳答案

似乎实际上对WSASend()的调用不是线程安全的,并且如果您打算从同一连接上的多个线程中调用WSASend(),则应进行同步,以便在任何给定点实际上只有一个线程在向API调用(例如,在WSASend()调用周围保持每个连接锁)。有关详细信息,请参见此问题和随附的测试代码:TCP/IP IOCP received data sometimes corrupt - Visual C++ on Windowsthis blog entry以获得更详细的说明。

还要注意,如果要使用来自多个线程的多个WSASend()调用发送不同的应用程序级别消息,则可能会出现问题,因为在将数据写入TCP流之前,多个调用可能会混合在一起。

所以,

如果您有5个线程发送“完整2字节消息”,以便您发送

来自5个不同线程的AA,BB,CC,DD,EE等,那么您将不会获得包含以下内容的流

ABCCDDBAEE

但您可以得到消息顺序的任意组合。

如果您的线程通过多个发送调用(例如三个发送)发送消息,则线程1中的A1 A2 A3形成一条应用程序级消息。然后所有的赌注都关闭了,您可能会得到

TCP流中的A1B1A2A3B2B3等。

如果稍后需要这样做,则可能需要在所有WSASend调用周围加某种类型的锁,以便可以将多个发送分组到单个应用程序级别的原子发送中,或者应该对单个WSASend调用使用多个WSABUF来收集将多个写入操作合并到一个调用中。

关于c++ - 从多个线程在同一套接字上发布许多wsasend,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26046966/

10-11 10:34