我有一个简单的 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 位。