C# TCP套接字SendAsync操作是否可以在不传输缓冲区列表中的所有字节的情况下完成?

C# TCP套接字SendAsync操作是否可以在不传输缓冲区列表中的所有字节的情况下完成?,c#,sockets,mono,C#,Sockets,Mono,在Mono3.12上,我使用TCP流Socket来实现基于请求的流协议。我正在使用设置多个数据缓冲区 在和的文档中,我找不到任何关于在使用BufferList时是否可以在不发送所有字节的情况下引发的内容,这给人留下了我们必须验证的印象 另一方面,这是一种保证 当应用程序调用BeginSend时,系统将使用 分离线程以执行指定的回调方法,并将 阻塞EndSend,直到套接字发送字节数 请求或引发异常。 当使用SocketAsyncEventArgs.BufferList时,规范对传输的字节数有何保

在Mono3.12上,我使用TCP流
Socket
来实现基于请求的流协议。我正在使用设置多个数据缓冲区

在和的文档中,我找不到任何关于在使用
BufferList
时是否可以在不发送所有字节的情况下引发的内容,这给人留下了我们必须验证的印象

另一方面,这是一种保证

当应用程序调用
BeginSend
时,系统将使用 分离线程以执行指定的回调方法,并将 阻塞
EndSend
,直到
套接字发送字节数
请求或引发异常。

当使用
SocketAsyncEventArgs.BufferList
时,规范对传输的字节数有何保证


假设事件是用完成的。

当将SendAsync与
SocketAsyncEventArgs.BufferList一起使用时,规范对传输的字节数有何保证?

首先,可以在发生错误时引发事件,在这种情况下,您可以假定并非所有字节都已传输。为此,您需要测试SocketAsyncEventArgs.SocketError是否为SocketError.Success。此外,如果您提到“规范”,我假定您指的是(Microsoft)Windows Sockets文档(因为您链接到该文档是为了获得SendAsync和其他描述)

为了弄清楚文档在成功调用已完成事件时对传输字节数的说明或暗示,我们必须采取一些步骤。第一步是查看SendAsync是否使用重叠I/O。文档中回答了这个问题。此机制的实现对于底层传输提供程序是强制性的,因此它是唯一保证可用于Windows套接字的重叠I/O机制。因此,SendAsync保证使用具有WSA_FLAG_OVERLAPPED属性的套接字

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

第二步是确定重叠I/O告诉我们与传输字节量相关的已完成事件的信令。这种情况在几个地方进行了描述,例如在本页:“当发送缓冲区被消耗时,将提供指示”。[WSASend]函数的备注部分给出了更详细的说明:“当传输使用缓冲区时,将出现完成指示,调用例程的完成或事件对象的设置”

这仍然为这个短语的确切解释留下了一些空间。基本上,它表示数据被套接字范围外的底层传输机制接受和确认。这并不一定意味着它已到达远程端点协议层,这取决于通信协议。对于TCP流套接字,我可以推断它指示数据已到达远程端点


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

你想在这里查什么?您是否关心在发送所有字节时为什么没有接收到所有字节


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

我想问题是:“是否可以调用
SocketAsyncEventArgs.Completed
处理程序而不出现套接字错误和
e.ByTestTransferred!=length
?”从我在.NET Framework下收集到的信息来看是不可能的:您能提供一些测试代码吗?@SotiriosDelimanolis.NET在Linux上也使用
sendmsg
。但它也会检查所有缓冲区是否都已发送。@ShmuelH。你能链接到你在Core中浏览的源代码吗?Mono似乎并没有做到这一点,至少从服用tcpdump(见本问题之前的编辑版本)来看是如此。此代码计算要发送的下一个索引和偏移量(在部分操作中,它将从下一个未发送的字节开始)。另请参见
TryCompleteSendTo
。是的,让我们仅假设
SocketError.Success
。我将编辑我的问题。我不相信。当我链接到文档时,我的目的是链接到.Net标准库,它应该由所有.Net运行时实现,而不仅仅是Windows。Windows实现是单向的,但这是唯一正确的方法吗?对于.NET Core(可以在Linux上运行)或Mono(例如Unity游戏引擎使用的),也可以在不同的平台上运行吗?