web-dev-qa-db-ja.com

C#でUdpClientのタイムアウトを設定できますか?

UdpClient receiveメソッドのタイムアウト値を設定できるかどうか疑問に思っています。

ブロックモードを使用したいのですが、udpによってパケットが失われることがあるので、プログラムudpClient.receiveが永久にハングします。

私がそれをどのように管理できるか良いアイデアはありますか?

35
Jack

Filipが参照しているのは、UdpClientに含まれるソケット(UdpClient.Client.ReceiveTimeout)。

非同期メソッドを使用してこれを行うこともできますが、実行を手動でブロックします。

var timeToWait = TimeSpan.FromSeconds(10);

var udpClient = new UdpClient( portNumber );
var asyncResult = udpClient.BeginReceive( null, null );
asyncResult.AsyncWaitHandle.WaitOne( timeToWait );
if (asyncResult.IsCompleted)
{
    try
    {
        IPEndPoint remoteEP = null;
        byte[] receivedData = udpClient.EndReceive( asyncResult, ref remoteEP );
        // EndReceive worked and we have received data and remote endpoint
    }
    catch (Exception ex)
    {
        // EndReceive failed and we ended up here
    }
} 
else
{
    // The operation wasn't completed before the timeout and we're off the hook
}
29
Brad Nabholz

SendTimeoutReceiveTimeoutで使用できるSocketおよびUdpClientプロパティがあります。

5秒のタイムアウトの例を次に示します。

var udpClient = new UdpClient();

udpClient.Client.SendTimeout = 5000;
udpClient.Client.ReceiveTimeout = 5000;

...
60
sep15ms

実際、タイムアウトに関してはUdpClientが壊れているようです。データを取得してキューに追加する受信のみを含むスレッドでサーバーを作成しようとしました。私はこの種のことを何年もの間TCPで行ってきました。期待は、メッセージがリクエスターから届くまで、ループが受信でブロックすることです。ただし、タイムアウトを無限に設定しても、次のようになります。

_server.Client.ReceiveTimeout = 0; //block waiting for connections
_server.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 0);

ソケットは約3分後にタイムアウトします。

私が見つけた唯一の回避策は、タイムアウト例外をキャッチしてループを続行することでした。これはマイクロソフトのバグを隠しますが、なぜこれが起こっているのかという根本的な質問に答えることはできません。

4
Pierre

あなたはこのようにすることができます:

udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);
3
Elyas Nategh

使用できるReceiveTimeoutプロパティがあります。

2
Filip Ekberg