2

我有一个简单的 C# 异步客户端,它使用 .NET 套接字等待来自用于自动化命令的本地 Java 服务器的定时消息。消息异步传入并写入环形缓冲区。此实现似乎在 Windows Vista/7/8 和 OSX 上运行良好,但在从本地 Java 服务器接收消息时会随机抛出此异常:

未处理的异常:System.InvalidOperationException:每个异步操作只能调用一次 EndReceive。
    在 System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult, SocketError& errorCode)
    在 System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
    在 SocketTest.Controller.RecvAsyncCallback(IAsyncResult ar)
    在 System.Net.LazyAsyncResult.Complete( IntPtr userToken)
    ...

我在网上查找了这个错误,但没有发现任何真正有用的东西。这是似乎中断的代码:

/// <summary>
/// Callback to receive socket data
/// </summary>
/// <param name="ar">AsyncResult to pass to End</param>
private void RecvAsyncCallback(IAsyncResult ar)
{
    // The exception will randomly happen on this call
    int bytes = _socket.EndReceive(_recvAsyncResult);

    // check for connection closed
    if (bytes == 0)
    {
        return;
    }

    _ringBuffer.Write(_buffer, 0, bytes);

    // Checks buffer
    CheckBuffer();

    _recvAsyncResult = _sock.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, RecvAsyncCallback, null);
}

该错误不会在任何特定时刻发生,除非在接收消息的中间。消息本身可以是任意长度以使这种情况发生,异常可以立即发生,有时甚至长达一分钟的完美通信。

我对套接字和网络通信很陌生,我觉得我可能在这里遗漏了一些东西。我已经在至少 8 台不同的计算机上进行了测试,与抛出此异常的计算机的唯一相似之处是它们的操作系统是 Windows XP 32 位。

4

1 回答 1

1

您将需要遵循此处显示的约定。您传入的IAsyncResulttoSocket.BeginReceive代表上下文中的不同点或完全不同的上下文。

确保在您的回调中使用调用时传入的参数EndReceive

Windows XP 中可能有一个错误修复,这取决于您的服务包和您安装的其他东西,它捕获了上下文共享场景,或者它可能引入了一个错误,它不能正确管理上下文。如果没有广泛的测试,很难判断这是否是环境问题。

于 2013-11-07T21:51:56.417 回答