检查SendAsync是否已经发送完成。

3
在下面的简化代码中,检查SendAsync()是否已完成传输缓冲区中所有预期字节是正确的吗?或者这是多余的吗?这是针对TCP连接套接字的。我特别关注必须在ProcessSend()中发出第二个子调用SendAsync()的问题。
例如,如果我有多个线程使用每个消息的新(池化的)SocketAsyncEventArg向客户端传输数据,那么是否可能会发生同时发送插入到部分传输的消息之间?或者这是只允许使用一个SocketAsyncEventArg来发送数据的受控访问客户端的好理由?
private void ProcessSend(SocketAsyncEventArgs e)
{
    // Check that data was sent
    if ((e.SocketError == SocketError.Success) && (e.BytesTransferred > 0))
    {
        AsyncSendUserToken token = (AsyncSendUserToken)e.UserToken;

        // Check that all the data was sent
        int offset = e.Offset + e.BytesTransferred;
        if (offset < e.Count)
        {
            // Call send again to finish the send
            e.SetBuffer(offset, e.Count - offset);
            bool _willRaiseEvent = token.Socket.SendAsync(e);
            if (!_willRaiseEvent)
                ProcessSend(e);
        }
    }
}

我也见过这种情况,也看到过传输的字节数大于 e.Count - e.Offset 的情况。我在发送时重用了一个 SocketAsyncEventArgs,并调用了一个从 ProcessSend 中填充缓冲区并调用 SendAsync 的方法。我在 ProcessSend 中添加了代码以处理当前 SocketAsynEventArgs 并创建一个新的,这样就避免了出现此错误。 - Tim Carter
2个回答

2

我知道这个问题有点老,但是这个答案是否仍然适用于所有不同的.NET版本,比如.NET Core、Mono等?还是这个答案只对“常规”的Windows .NET版本有效? - R1PFake
请参阅 https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.sendasync?view=netframework-4.8#applies-to 以获取支持的 .NET 版本。 - Mikael Svenson
这些其他的.NET版本也支持该方法,但我的问题是,由于官方文档中没有提到,所以对于所有这些版本,是否真的如声明中所述:“当执行发送操作时,由于框架会为您处理所有数据的发送,因此此语句是多余的。” 我们“知道”在Windows上的.NET是正确的,但是对于其他平台,例如.NET Core和Mono可以在Linux上运行,但我不确定,因为我对Linux网络一无所知。 但我认为他们都应该实现相同的逻辑? - R1PFake
只要根据文档缓冲区在基础套接字缓冲区内,是可以的。如果您需要发送更多数据,您应该查看类似于 https://dev59.com/1mDVa4cB1Zd3GeqPaSAH 的资源。 - Mikael Svenson

1

我认为你的代码有问题:

// Check that all the data was sent
int offset = e.Offset + e.BytesTransferred;
if (offset < e.Count)
{

e.Count是要传输的字节数,而不是字节数组的偏移量。

因此,为了比较相同的内容,你可以这样写:

if (e.BytesTransfered < e.Count) { }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接