TCP Socket SendAsync操作是否可以在不传输BufferList中的所有字节的情况下完成?

问题描述 投票:18回答:2

在Mono 3.12上,我使用Socket.SendAsync(SocketAsyncEventArgs)和TCP Stream Socket来实现基于请求的流媒体协议。我正在使用SocketAsyncEventArgs.BufferList设置多个数据缓冲区。

SocketSocketAsyncEventArgs的文档中,我找不到任何关于在使用SocketAsyncEventArgs.Completed时是否可以在没有发送所有字节的情况下引发BufferList,留下我们必须对SocketAsyncEventArgs.BytesTransferred进行验证的印象。

另一方面,Socket.BeginSend做出了这种保证

当你的应用程序调用BeginSend时,系统将使用一个单独的线程来执行指定的回调方法,并将在EndSend上阻塞,直到Socket发送所请求的字节数或抛出异常。

当使用SendAsyncSocketAsyncEventArgs.BufferList时,规范对传输的字节数有什么保证?

假设事件是用SocketError.Success完成的。

c# sockets mono
2个回答
2
投票

当使用带有SocketAsyncEventArgs.BufferList的SendAsync时,规范对传输的字节数有什么保证?

首先,可以在错误时引发事件,在这种情况下,您可以假设并非所有字节都已传输。为此,您需要测试SocketError.Success的SocketAsyncEventArgs.SocketError。此外,如果您参考“规范”,我假设您的意思是(Microsoft)Windows套接字文档(因为您链接到此以获取SendAsync和其他说明)。

为了在成功的情况下调用Completed事件时,为了确定文档所说或暗示的传输字节数,我们必须做几个步骤。第一步是查看SendAsync是否使用重叠I / O.这个问题在Overlapped Input / Output文档中得到了解答。对于底层传输提供程序,此机制的实现是必需的,因此它是唯一可以保证可用于Windows套接字的重叠I / O机制。因此,SendAsync保证使用具有WSA_FLAG_OVERLAPPED属性的套接字。

请注意,检查SendAsync reference implementation表明SendAsync确实使用了带有重叠I / O的WSASend,但这只是一个观察。

第二步是确定重叠的I / O告诉我们关于已完成事件的信令与传输字节数量的关系。这种情况在几个地方有描述,例如在这个Overlapped I/I and Event Objects页面:'当发送缓冲区被消耗时将提供指示'。 [WSASend]函数的备注部分给出了更多详细信息:'当完成传输时,将调用例程的完成或事件对象的设置时,将发生完成指示' 。

这仍然留有一些空间来准确解释这句话。基本上它表示数据已被套接字范围内的底层传输机制接受和确认。这并不一定意味着它已到达远程端点协议层,这将取决于通信协议。对于TCP流式套接字,我推断它表明数据已到达远程端点。

这里的结论是文档保证(对于非错误情况)SendAsync completed事件仅在所有字节都已传输时引发。


-2
投票

你想在这里查看什么?您是否担心在发送所有字节时没有收到所有字节的原因?

当您一次发送100个字节并尝试在另一端读取100个字节时,无法保证您将一次性接收所有字节。它可以分成100个1字节的数据包。这就是TCP的工作原理。您总是需要累积字节,然后形成并分离您的数据包。这就是所谓的TCP套接字管道工作。 WCF和所有这些包装器都是为你做的。

© www.soinside.com 2019 - 2024. All rights reserved.