关于C#:从多个线程在同一个套接字上发布许多wsasend

post many wsasend on the same socket from multiple threads

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

MSDN这样说:

If you are using I/O completion ports, be aware that the order of
calls made to WSASend is also the order in which the buffers are
populated. WSASend should not be called on the same socket
simultaneously from different threads, because it can result in an
unpredictable buffer order.

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

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

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


似乎实际上对WSASend()的调用不是线程安全的,并且如果您打算从同一连接上的多个线程中调用WSASend(),则应进行同步,以便在任何情况下只有一个线程实际上在对API进行调用给定点(即在WSASend()调用周围保持每个连接锁定)。有关详细信息,请参见此问题和随附的测试代码:TCP / IP IOCP接收的数据有时会损坏-Windows上的Visual C和此博客条目以获取更详细的说明。

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

所以

如果您有5个线程发送"完整2字节消息",以使您发送

来自5个不同线程的

AA,BB,CC,DD,EE等,那么您将不会获得包含

的流

ABCCDDBAEE

,但您可以获取消息顺序的任意组合。

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

结尾

TCP流中的

A1B1A2A3B2B3等。

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