最近我解決了.Net同步接收方法的一個奇怪行爲。我需要編寫一個應用程序,它具有通過發送/接收數據相互通信的節點。每個服務器都有一個同步的接收循環,接收到一個序列化的類後,它將對其進行反序列化並對其進行處理。之後,它將這個序列化的類異步發送給一些選定的節點(使用AsynchSendTo)。.NET C#同步接收不會阻止
的MSDN明確說:
「如果您使用的是面向連接的插座,Receive方法 將讀取儘可能多的數據是可用的,直到緩衝區的大小 如果。遠程主機使用Shutdown 方法關閉Socket連接,並且已收到所有可用數據,接收方法 將立即完成並返回零字節。「
在我的情況是不正確的。在Receive建立連接之後,有一些隨機情況會立即阻塞並返回0字節(非確定性位置)。我100%確定發件人發送的是至少1000字節。另一個有趣的事實是:在收到之前將睡眠(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;
}
我的問題:我使用的同步收到一條錯誤的路?儘管有數據要接收,爲什麼它不阻止事件?
由於您的問題並不是專門針對您在閱讀前通過睡眠解決的問題。如果一次讀取很多,每個循環都會有半個秒的延遲,所以您是否嘗試了睡眠後睡眠時間更短,比如100msecs?這對我來說很適合從串口讀取數據,但也是在發生數據接收事件時。 – jlafay
這只是套接字的工作方式。通過刪除所有try/catch塊來開始診斷。 –