2017-01-04 26 views
18

在Mono 3.12上,我使用Socket.SendAsync(SocketAsyncEventArgs)和TCP流Socket来实现基于请求的流式协议。我使用SocketAsyncEventArgs.BufferList来设置多个数据缓冲区。完成TCP Socket SendAsync操作而不传输BufferList中的所有字节?

在为SocketSocketAsyncEventArgs的文档,我无法找到的是否为SocketAsyncEventArgs.Completed,而不当使用BufferList发送的所有字节,使我们必须验证对SocketAsyncEventArgs.BytesTransferred的印象中引发的任何提及。

在另一方面,Socket.BeginSend使得这样的保证

当应用程序调用BeginSend,该系统将使用 单独的线程执行指定的回调方法,并将 块EndSend直到Socket发送请求的字节数 或引发异常。

不规范作出关于使用SendAsyncSocketAsyncEventArgs.BufferList时传输的字节数是什么保证?

假设事件已完成SocketError.Success

+1

我想问题是:“SocketAsyncEventArgs.Completed'处理程序是否可以在没有套接字错误和'e.BytesTransferred!= length'的情况下被调用?”从我可以在.NET框架下收集是不可能的:http://stackoverflow.com/questions/28675811/when-i-call-wsasend-will-all-the-data-be-sent和http:// stackoverflow .com/questions/14347708/calling-wsasend-in-completion-port – jorgebg

+0

你能提供一些测试代码吗? –

+0

@DieterMeemken你需要测试什么来回答_规范做了什么保证?正如我所提到的,我将'SendAsync'与'SocketAsyncEventArgs'一起使用并设置了一个'BufferList'。 –

回答

1

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

首先,可以针对错误引发事件,在这种情况下,您可以假设并非所有字节都已传输。为此,您需要为SocketError.Success测试SocketAsyncEventArgs.SocketError。另外,如果你引用'规范',我假设你的意思是(Microsoft)Windows套接字文档(因为你链接到这个SendAsync和其他描述)。

为了确定文档中说明或暗示了在成功完成事件调用时传输的字节数,我们必须执行几个步骤。第一步是查看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已完成事件仅在所有字节已传输时发生。

+0

是的,让我们假设只有'SocketError.Success'。我会编辑我的问题。我不相信。当我链接到文档时,我的意图是链接到.Net标准库,应该由所有.Net运行时实现,而不仅仅是Windows。 Windows的实现可以做到这一点,但这是唯一正确的方法吗? –

-1

你想在这里检查什么?你是否担心在发送所有字节时你没有收到所有字节?

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