套接字发送与 sendasync。啥时候发送实际阻塞?
Posted
技术标签:
【中文标题】套接字发送与 sendasync。啥时候发送实际阻塞?【英文标题】:Socket send vs sendasync. When does send actually block?套接字发送与 sendasync。什么时候发送实际阻塞? 【发布时间】:2012-09-09 23:34:11 【问题描述】:阅读 MSDN 页面,很明显,如果套接字传输层中没有内部缓冲区,Send 将阻塞。这实际上是一件好事,因为我宁愿没有 NoBufferSpaceAvailable 错误。我的理解是传输缓冲区空间很大,但如果 Send 限制了一些东西以防止这些错误,我很高兴。
但是,尚不清楚还有什么会导致 Send 被阻止。我的猜测是它不会阻塞等待发送的确认,并且发送只会将数据排队到传输缓冲区并返回。
如果一个 Send 确实阻塞,直到一个特定的套接字实际上完全阻塞,直到传输完成,这将是一件非常糟糕的事情。如果是这种情况,那么 1000 个中的一个慢速连接可能会减慢整个发送过程。在那种情况下,SendAsync 确实是强制性的。
谁有这方面的更多细节?
【问题讨论】:
如果你等待异步套接字返回一些东西(即:结果。),它也会阻塞。 【参考方案1】:正如 EJP 所说,发送缓冲区负责处理任何未确认的数据,也就是说,您发送的任何数据都将保留在缓冲区中,直到被接收方确认为止。这是为了允许稍后重新发送数据,以防数据包的 ACK 永远不会到达。
此外,正如 EJP 所说,每当收到 ACK 时,刚刚确认的数据就会从发送缓冲区中删除,并释放空间,以便您可以将其用于进一步发送。
但是,在发送大量数据并且 ACK 回复缓慢的情况下(由于高延迟、嘈杂的连接或只是在途中断开连接),那么发送缓冲区将被填满并且将由于发送缓冲区空间不足,最终导致发送阻塞。
因此,未确认的数据本身不会直接导致发送阻塞,但如果您发送大量数据并且存在网络问题,这意味着 ACK 无法返回给您,那么是的......未确认数据最终会导致发送阻塞。这是正确的行为。
您不希望在没有收到 ACK 的情况下一直发送数据。如果您确实想要,那么您可能会使用 UDP 而不是 TCP :)
编辑:此外,每个连接使用一个线程并不少见,以避免您提到的特定情况,即一个错误的连接会影响一千个。如果您担心扩展,您可能应该使用异步调用。
【讨论】:
如果接收方跟不上发送方,发送缓冲区也会因滑动窗口耗尽而填满。 谢谢。猜猜我会搬到 beginsend 或 sendasync 然后。还没有看到任何发送阻塞,但它一定会发生,我不希望它阻塞我的发送线程,或者每次发送使用一个线程。干杯。【参考方案2】:在收到该发送的 ACK 之前,TCP 发送不会阻塞。这就是缓冲的用途。发送是缓冲的,只有在缓冲区满时才会阻塞。同时,TCP 异步将缓冲区的内容发送给对等方,并在收到 ACK 时丢弃它们。
【讨论】:
因此,SendAsync 对程序员来说似乎没有什么价值。然而 ReceiveAsync 确实有很大的价值。并且具有 Async 的更高级别的请求-响应模式确实具有价值(纯粹用于响应方面)。以上是关于套接字发送与 sendasync。啥时候发送实际阻塞?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 SmtpClient.SendAsync 发送带有附件的电子邮件?
HttpClient.SendAsync() 未将 JSON 作为字符串发送