【问题标题】:Checking whether SendAsync has finished sending检查 SendAsync 是否发送完毕
【发布时间】:2009-12-21 05:20:56
【问题描述】:

在下面的简化代码中,检查 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 并创建一个新的,这已经阻止了这个错误的发生。

标签: c# multithreading sockets sendasync


【解决方案1】:

我怀疑您正在阅读http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx 的示例,并看到他们正在检查 ProcessReceive 上的字节长度。

这样做是为了获取所有接收到的字节,因为您无法控制每次从对方发送多少字节。

当您执行发送时,这是多余的,因为框架会为您处理发送所有数据。

【讨论】:

  • 我知道这个问题已经过时了,但是对于所有不同的 .NET 版本(如 .NET Core、Mono 等)来说,这个答案是否仍然正确,或者这个答案仅对“正常”/Windows .NET 有效版本?
  • 查看 docs.microsoft.com/en-us/dotnet/api/… 了解受支持的 .NET 版本
  • 这些其他 .NET 版本也支持该方法,但我的问题是“当您执行发送时,这是多余的,因为框架会为您发送所有数据。”对于所有这些版本都是如此,因为它不在任何这些版本的官方文档中。我们“知道”Windows 上的 .NET 确实如此。但在其他平台上可能会有所不同,例如 .NET Core 和 Mono 可以在 Linux 上运行,但我不确定,因为我不知道 Linux 网络。但我假设他们都应该实现相同的逻辑?
  • 只要缓冲区在底层套接字缓冲区中,按照文档是的。如果您需要发送更多数据,您应该查看stackoverflow.com/questions/9170126/…
【解决方案2】:

我认为你的代码有问题:

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

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

所以,为了比较苹果和苹果,你会说:

如果(e.BytesTransfered

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多