最近、私は.Net同期受信メソッドの奇妙な動作に取り組んでいます。私はデータを送受信することによって互いに通信するノードを持つアプリケーションを書く必要がありました。各サーバーにはシリアライズされたレシピ・ループがあり、シリアライズされたクラスを受け取った後、シリアライズされて処理されます。その後、(AsynchSendToを使用して)このシリアル化されたクラスをいくつかの選択されたノードに非同期で送信します。.NET C#同期受信はブロックされません
MSDNを明確にすることを言います:あなたは、接続指向のソケットを使用している場合は、バッファのサイズまで、利用可能であるとして、受信方法 は、できるだけ多くのデータを読み込みます
」 場合。リモートホストはシャットダウン メソッドでソケット接続をシャットダウンし、利用可能なすべてのデータを受信した場合、受信方法 はすぐに完了し、ゼロバイトを返します。
私の場合、それは真実ではありません。 Receiveが接続を確立した直後に0バイト(非確定的なシチュエーション)をブロックして返さないランダムなケースがいくつかあります。私は、送信者が少なくとも1000バイトで送信していることを100%確信しています。もう一つの面白い事実:スリープ(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;
}
私の質問:私は、同期は間違った方法で受信使用していますか?受信するデータがあるのにイベントをブロックしないのはなぜですか?
あなたの質問は、読解前に睡眠中に解決されている問題に関するものではないので、一度にたくさん読んでいる場合、各ループの半分の時間が実際に待ち時間を取ることができるので、100msecのような小さなスリープ時間で読んだ後に眠ってみましたか?これはシリアルポートからの読み込みで私にとってはうまくいきましたが、データ受信イベントも発生しました。 – jlafay
これはちょうどソケットが動作する方法ではありません。すべてのtry/catchブロックを削除して診断を開始します。 –