(问题是从msdn论坛复制的)
MSDN说:
如果您正在使用I / O完成端口,请注意其顺序 对WSASend的调用也是缓冲区的顺序 填充。不应在同一个套接字上调用WSASend 同时来自不同的线程,因为它可以导致一个 不可预测的缓冲顺序。
好的......但如果我不关心这个订单而且也不关心订单,我会在另一边收到它...那我可以使用它吗?从多个线程调用WSASend是否安全?我将如何传递包裹(可能以不同方式排序,但完整)??
E.g。 - >我发送[12a],[34b],[11c]和[223d] ......([]标记我在一次通话中传递给WSASend的单位) 34b,11c,12a,223d?还是会崩溃?或者我可以收到诸如2a,34b,7a,5c ......之类的东西。
所以,也许问题应该是 - >它是线程安全的吗?它是原子的吗? (我说的是WSASend与IOCPs一起使用,所以OVERLAPPED)
答案 0 :(得分:2)
实际上对WSASend()的实际调用似乎不是线程安全的,如果你打算从同一连接上的多个线程调用WSASend(),那么你应该进行同步,以便只有一个线程实际调用任何API。给定点(即在WSASend()调用周围保持每个连接锁)。有关详细信息,请参阅此问题和附带的测试代码:TCP/IP IOCP received data sometimes corrupt - Visual C++ on Windows和this blog entry以获得更详细的说明。
另请注意,如果您使用多个线程的多个WSASend()调用发送不同的应用程序级别消息,则会出现问题,因为在将数据写入TCP流之前可能会混合多个调用。
所以,
如果您有5个线程发送'完成2个字节的消息'这样你发送
来自5个不同线程的AA,BB,CC,DD,EE等,那么你将无法获得包含的流ABCCDDBAEE
但您可以获得任何消息顺序组合。
如果你的线程正在发送带有多个发送调用的消息,那么三个发送,来自线程1的A1 A2 A3形成单个应用程序级消息。然后所有的赌注都会关闭,因为你最终可以
A1流中的A1B1A2A3B2B3等。
如果您需要执行稍后操作,您将需要围绕所有WSASend调用的某种锁定,以便您可以将多个发送分组到单个应用程序级别的原子发送中,或者您应该为单个WSASend使用多个WSABUF打电话将多个写入聚集在一起。