异步写入套接字线程是否安全?
考虑Socket.BeginSend()
方法。 如果两个线程池线程同时调用此方法,它们各自的消息是否最终会相互混合,或者套接字类是否阻止这种情况发生?
我在MSDN论坛上发现了一个熟悉的post,它似乎回答了你的问题。
- 您可以同时排队多个BeginSends。 你不需要锁定
编辑:
更有趣的信息:
如果在MSDN doc BeginSend()的“ 备注”部分向下滚动一下,您会发现可能与您相关的回调方法的有趣用法。
[…]如果您希望在调用BeginSend方法后阻止原始线程,请使用WaitHandle.WaitOne方法。 […]
.NET Socket实例不是线程安全的,因为同时调用某些方法(相同或不同的方法)可能会导致状态不一致。 但是, BeginSend()
和BeginReceive()
方法相对于自身是线程安全的 。
对每个(或两个)进行多次未完成的呼叫是安全的。
在BeginReceive()
的情况下,当数据在调用的顺序中可用时,它们将被服务。 例如,如果您的处理过长但希望尽快发生其他接收,则此function非常有用。 当然,在这种情况下,您可能会让代码同时处理多个收据,您可能需要自己的同步逻辑来保护您的应用程序状态。
在BeginSend()
的情况下,每次调用都会尝试将发送的数据推送到套接字缓冲区,一旦被接受,就会调用你的回调(你将调用EndSend()
)。 如果任何调用没有足够的缓冲区空间,它将阻塞。
注意:不要假设默认的8k缓冲区意味着“我可以用8k的数据快速调用BeginSend()
,然后它将阻塞”,如下所示:
-
8K是“标称大小”数,缓冲区可能会缩小并有所增长
-
当您排队等待8K的呼叫时,将在网络上发送数据,减少8K的排队数据
一般来说:
-
如果在一个线程中多次调用
BeginSend()
,则可以确保发送将按照调用它们的顺序离开机器。 -
如果从多个线程调用
BeginSend()
,则无法保证顺序,除非您使用其他阻塞机制强制实际调用以某种特定顺序发生。 然而,每个呼叫将在一个连续的网络字节流中正确地发送其数据。