最近我解决了 .Net 同步接收方法的一个奇怪行为。我需要编写一个应用程序,该应用程序具有通过发送/接收数据相互通信的节点。每个服务器都有一个同步的接收循环,在接收到一个序列化的类后,它反序列化并处理它。之后,它将这个序列化类异步发送到一些选定的节点(使用 AsynchSendTo)。
MSDN 明确指出:
"If you are using a connection-oriented Socket, the Receive method will read as much data as is available, up to the size of the buffer. If the remote host shuts down the Socket connection with the Shutdown method, and all available data has been received, the Receive method will complete immediately and return zero bytes."
在我看来,这不是真的。在某些随机情况下,接收不会阻塞并在建立连接后立即返回 0 字节(非确定性情况)。我 100% 确定发件人至少发送了 1000 个字节。还有一个有趣的事实:当在 receive 之前放置 Sleep(500) 时,一切正常。以下是接收代码:
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
_listener.Bind(_serverEndpoint);
_listener.Listen(Int32.MaxValue);
while (true)
{
Console.WriteLine("Waiting for connection...");
Socket handler = _listener.Accept();
int totalBytes = 0;
int bytesRec;
var bytes = new byte[DATAGRAM_BUFFER];
do
{
//Thread.Sleep(500);
bytesRec = handler.Receive(bytes, totalBytes, handler.Available, SocketFlags.None);
totalBytes += bytesRec;
} while (bytesRec > 0);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
catch (SocketException e)
{
Console.WriteLine(e);
}
还有发送部分:
public void AsynchSendTo(Datagram datagram, IPEndPoint recipient)
{
byte[] byteDatagram = SerializeDatagram(datagram);
try
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.BeginConnect(recipient, ConnectCallback, new StateObject(byteDatagram, byteDatagram.Length, socket));
}
catch (SocketException e)
{
Console.WriteLine(e);
}
}
public void ConnectCallback(IAsyncResult result)
{
try
{
var stateObject = (StateObject)result.AsyncState;
var socket = stateObject.Socket;
socket.EndConnect(result);
socket.BeginSend(stateObject.Data, 0, stateObject.Data.Length, 0, new AsyncCallback(SendCallback), socket);
}
catch (Exception ex)
{
Console.WriteLine("catched!" + ex.ToString());
}
}
public void SendCallback(IAsyncResult result)
{
try
{
var client = (Socket)result.AsyncState;
client.EndSend(result);
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
class StateObject
{
public Byte[] Data { get; set; }
public int Size;
public Socket Socket;
}
我的问题:我是否以错误的方式使用了同步接收?为什么有数据要接收却不阻塞事件?
最佳答案
你是搬起石头砸自己的脚。
bytesRec = handler.Receive(bytes, totalBytes, handler.Available, SocketFlags.None);
在连接的最开始,Available
将为 0,强制它立即返回 0。相反,您应该指定缓冲区中空闲的字节数(例如 bytes.Length-totalBytes
), 那么它也会阻塞。
关于c# - .NET C# 同步接收不阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8168078/