none
UdpClient.ReceiveがWSAECONNRESETを投げるとき、Client.Blockingは破損します RRS feed

  • 質問

  • 以下のようなコードを書きました。

     UdpClientを使った2スレッド・ブロッキング通信ですが、相手先にICMP port unleachableを返すようなホスト:ポートの組み合わせを選びます(要するに相手サービスが死んでいるときのテストです)

     SendしたあとICMPが戻ってくると、ブロックしていたReceiveがWSAECONNRESET(System.Net.Sockets.SocketException: 既存の接続はリモート ホストに強制的に切断されました) を投げます。これ自体は予期したことで、そのためにcatchしています。

    問題はこれからで、それ以降Receiveを呼ぶと即座にWSAEWOULDBLOCK( System.Net.Sockets.SocketException: ブロック不可のソケット操作をすぐに完了できませんでした)を投げます。例外が例外なので、catchしたついでに、udp.Client.Blocking=true;とやってみると、期待した動作になります(パケットを待つようににある)。代入する前も、udp.Client.Blocking.ToString()は"true"とか云うので、内部で何か状態変化を戻し損ねているのでしょうか。

     XP SP2と、Vista双方で、ファイヤーウォール無効 の条件で再現しますが、こういうものなんでしょうか。

    #なんかタイトルがKBみたいな気がする・・・

     

    Code Snippet

    using System.Net;
    using System.Net.Sockets;
    class Test
    {
      static byte[] send = new byte[] { 0, 1, 2 };
      static void Main(){
        UdpClient udp = new UdpClient("localhost", 30000);
        System.Threading.ThreadPool.QueueUserWorkItem(delegate(object o){
          while (true){
            System.Console.WriteLine("W");
            udp.Send(send, send.Length);
            System.Threading.Thread.Sleep(1000);
          }
        }, null);
       
        while (true){
          IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
          try {
            byte[] b = udp.Receive(ref ep);
          }catch (SocketException e){
            System.Console.WriteLine(e.ToString());
          }
        }
      }
    }

     

     

    2008年3月17日 12:27