2013-03-31 1 views
0

멀티 캐스트 주소에서 UdpSocket을 통해 데이터를 수신하려고합니다. 소켓을 통해 데이터를 보내기 전에 소켓에서 데이터를받지 못합니다. 전송 후, 나는 몇 가지 패키지를받을 수 있으며, 나는 다시 패키지를 받기 전에 다시 보내야한다. 한편 다른 호스트에서 보낸 패키지는 손실됩니다. whireshark가 모든 패키지를 받기 때문에 방화벽과 같은 문제가 아닌 것 같습니다 (C# UDP Socket doesn't receive data until after data is sent). 누군가이 행동을 설명 할 수 있습니까?C# UdpSocket은 전송 후 수신을 시작하고 몇 개의 패키지를받은 후에 수신을 중지합니다.

class Program 
{ 
    private static UdpClient _mdnsSocket; 
    private static IPEndPoint _mdnsGroup; 
    private static IPEndPoint _localEp; 

    static void Main(string[] args) 
    { 
     var interfaces = NetworkInterface.GetAllNetworkInterfaces() 
             .Where(i => i.OperationalStatus == OperationalStatus.Up) 
             .ToArray(); 

     for (int i = 0; i < interfaces.Length; ++i) 
     { 
      var interf = interfaces[i]; 
      Console.WriteLine("{0}) Name: {1}", i, interf.Name); 
     } 
     Console.WriteLine(); 

     do 
     { 
      int i; 
      Console.Write("Interface: "); 
      var line = Console.ReadLine(); 
      if (int.TryParse(line, out i) && i < interfaces.Length) 
      { 
       var addr = interfaces[i].GetIPProperties() 
             .UnicastAddresses.FirstOrDefault(a => a.Address.AddressFamily == AddressFamily.InterNetwork); 
       if (addr != null) 
       { 
        _localEp = new IPEndPoint(addr.Address, 5353); 
        Console.WriteLine("Choosen IP: {0}", _localEp); 
       } 
      } 
     } while (_localEp == null); 


     _mdnsGroup = new IPEndPoint(IPAddress.Parse("224.0.0.251"), 5353); 
     _mdnsSocket = new UdpClient(); 
     _mdnsSocket.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
     _mdnsSocket.ExclusiveAddressUse = false; 
     _mdnsSocket.Client.Bind(_localEp); 
     _mdnsSocket.JoinMulticastGroup(_mdnsGroup.Address, _localEp.Address); 
     BeginReceive(); 

     Console.WriteLine("1 to switch to multicast mode (default)"); 
     Console.WriteLine("2 to switch to unicast mode"); 
     Console.WriteLine("s for sending a message"); 
     Console.WriteLine("ESC for exit"); 

     ConsoleKey key; 
     IPEndPoint ip = _mdnsGroup; 
     IPEndPoint unicastip = null; 
     var mode = "multicast"; 

     do 
     { 
      Console.Write("1/2/s/ESC: "); 
      key = Console.ReadKey().Key; 
      Console.WriteLine(); 

      switch (key) 
      { 
       case ConsoleKey.D1: 
        ip = _mdnsGroup; 
        Console.WriteLine("Switched to multicast mode"); 
        mode = "multicast"; 
        break; 

       case ConsoleKey.D2: 
        Console.Write("Enter new IP (leave empty to use {0}):", unicastip); 
        var input = Console.ReadLine(); 
        if (string.IsNullOrEmpty(input)) 
        { 
         if (unicastip == null) 
         { 
          Console.WriteLine("error: no last ip!"); 
          break; 
         } 
         ip = unicastip; 
         Console.WriteLine("Switched to unicast mode"); 
         mode = "unicast"; 
        } 
        else 
        { 
         unicastip = new IPEndPoint(IPAddress.Parse(input), 5353); 
         ip = unicastip; 
         Console.WriteLine("Switched to unicast mode"); 
         mode = "unicast"; 
        } 
        break; 

       case ConsoleKey.S: 
        var msg = string.Format("Hello from PC via {0}", mode); 
        var bytes = Encoding.ASCII.GetBytes(msg); 

        Console.WriteLine("Sending to {0}", ip); 
        _mdnsSocket.Send(bytes, bytes.Length, ip); 
        break; 
      } 
     } while (key != ConsoleKey.Escape); 
     _mdnsSocket.Close(); 
    } 

    private static void BeginReceive() 
    { 
     Console.WriteLine("BeginReceive"); 
     _mdnsSocket.BeginReceive(ReceiveCallback, _mdnsSocket); 
    } 

    private static void ReceiveCallback(IAsyncResult ar) 
    {    
     try 
     { 
      var ep = new IPEndPoint(IPAddress.Any, _mdnsGroup.Port); 
      var data = _mdnsSocket.EndReceive(ar, ref ep); 

      var message = Encoding.ASCII.GetString(data); 
      Console.WriteLine(message); 
     } 
     finally 
     { 
      BeginReceive(); 
     } 
    } 
} 
+0

btw : 동일한 init/send/receive 코드가 내 안드로이드 (xamarin.droid로 컴파일 됨)에서 작동합니다. o0 Plz이 말하지 않습니다. .NET 구현 문제 :( –

답변

0

결국 방화벽 문제였습니다. 포트 5353에서 들어오는 UPD를 명시 적으로 허용하면 작동 함 (해당 프로그램에 대해 들어오는 UPD 트래픽을 허용하지 않는 이유). 이제는 hole punching 메커니즘을 사용하여 질문에 설명 된 동작을 설명합니다. 내가 틀렸을 때 나를 바로 잡아주세요.

관련 문제