异步写入套接字线程是否安全

本文关键字:是否 安全 线程 套接字 异步 | 更新日期: 2023-09-27 18:31:15

考虑Socket.BeginSend()方法。如果两个线程池线程同时调用此方法,它们各自的消息最终会相互混合还是套接字类阻止这种情况发生?

异步写入套接字线程是否安全

.

NET Socket 实例不是线程安全的,因为同时调用某些方法(相同或不同的方法)可能会导致状态不一致。 但是,BeginSend()BeginReceive() 方法相对于自身是线程安全的

每个(或两个)有多个未完成的调用是安全的。

BeginReceive()的情况下,当数据按调用的顺序可用时,它们将被服务。例如,如果您的处理时间很长,但您希望尽快发生其他接收,则这可能很有用。当然,在这种情况下,您的代码可能会同时处理多个收据,并且可能需要自己的同步逻辑来保护应用程序状态。

BeginSend() 的情况下,每次调用都会尝试将发送的数据推送到套接字缓冲区中,一旦在那里被接受,您的回调就会被调用(您将在其中调用 EndSend())。如果没有足够的缓冲区空间用于任何调用,它将阻塞。

注意:不要假设默认的 8k 缓冲区意味着"我可以用正好 8k 的数据快速调用BeginSend(),然后它会阻塞",因为以下情况是正确的:

  1. 8K是一个"标称尺寸"数字,缓冲区可能会缩小并增长一些

  2. 当您排队处理 8K 的呼叫时,数据将在网络上发送,从而减少 8K 的排队数据

通常:

  • 如果在线程中多次调用BeginSend(),则可以确保发送将按调用顺序离开计算机。

  • 如果从多个线程调用BeginSend(),则无法保证顺序,除非使用其他阻塞机制强制实际调用按某个特定顺序进行。但是,每个调用都将在一个连续的网络字节流中正确发送其数据。

我在MSDN论坛上发现了一个有趣的帖子,它似乎回答了你的问题。

  1. 您可以同时对多个开始发送进行排队。您无需锁定

编辑:

更多有趣的信息:

如果您在 MSDN 文档 BeginSend() 的备注部分中向下滚动一点,您会发现可能与您相关的回调方法的有趣用法。

[...]如果希望在调用 BeginSend 方法后阻止原始线程,请使用 WaitHandle.WaitOne 方法。[...]