2017-11-02 7 views
0

자동 검색 메커니즘을 구현하는 응용 프로그램이 있는데 UdpClient에 문제가 있습니다. 응용 프로그램의 단일 인스턴스가 열려있는 한 제대로 작동합니다. 그러나 두 번째 인스턴스가 열리면 첫 번째 인스턴스 만 유니 캐스트 패킷을 수신합니다. 흥미롭게도 같은 메커니즘을 구현하는 유사한 응용 프로그램에는이 문제가없는 것 같습니다. 어떤 제안?UdpClient는 여러 수신기에서 데이터를 수신합니다.

class AutoDiscovery 
{ 
    private UdpClient Udp; 
    private IPEndPoint BroadcastEP = new IPEndPoint(IPAddress.Broadcast, 1234); 
    private List<byte> AutoDiscoverPacket = new List<byte>(); 
    public ObservableCollection<DiscoveredDevice> DiscoveredDevices = new ObservableCollection<DiscoveredDevice>(); 

    public AutoDiscovery() 
    { 
     Udp = new UdpClient(); 
     Udp.ExclusiveAddressUse = false; 
     Udp.EnableBroadcast = true; 
     Udp.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
     Udp.Client.Bind(new IPEndPoint(IPAddress.Any, 1234)); 

     AutoDiscoverPacket.AddRange(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); 
     AutoDiscoverPacket.AddRange(Encoding.ASCII.GetBytes("SomeStaticString")); 
     while (AutoDiscoverPacket.Count < 123) 
     { 
      AutoDiscoverPacket.Add(0x00); 
     } 

     ReceiveDataAsync(ReceiveDataCallback); 
    } 

    ~AutoDiscovery() 
    { 
     if (Udp != null) 
     { 
      try 
      { 
       Udp.Close(); 
      } 
      finally 
      { 

      } 
     } 
    } 

    public void Discover() 
    { 
     DiscoveredDevices.Clear(); 
     Udp.Send(AutoDiscoverPacket.ToArray(), AutoDiscoverPacket.Count, BroadcastEP); 
    } 

    private void ReceiveDataAsync(Action<UdpReceiveResult> Callback) 
    { 
     Task.Run(async() => 
     { 
      try 
      { 
       while (true) 
       { 
        //IPEndPoint object will allow us to read datagrams sent from any source. 
        UdpReceiveResult receivedResults = await Udp.ReceiveAsync(); 
        Callback(receivedResults); 
       } 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     }); 
    } 

    private void ReceiveDataCallback(UdpReceiveResult Result) 
    { 

     // Do stuff here 
    } 
} 

}

+0

저는 한 번에 하나의 응용 프로그램 만 특정 IP/포트에 바인딩 될 수 있다고 생각합니다. 아마도이 방향으로 검색을 시도해 볼 수 있습니다. – casiosmu

답변

1

IP 주소와 포트의 동일한 조합에 하나 개 이상의 소켓을 결합하는 데 유용하지 않고, 기본적으로도 불가능합니다. SO_REUSEADDR 옵션 (관리 코드에서 SocketOptionName.ReuseAddress)을 설정 한 경우에만 소켓이 동일한 IP 주소의 포트를 공유 할 수 있으며 동작이 비 결정적입니다 (일반적으로 하나 또는 다른 소켓은 데이터 그램을 수신하지만 둘다는 수신하지 않습니다).

동일한 IP 주소를 사용하도록 소켓을 구성 할 수 있다면 (예 : 같은 컴퓨터에 여러 개의 네트워크 어댑터가있는 경우) 동일한 포트에서 수신 대기 할 수 있습니다.

보다 일반적인 접근 방법은 UDP 멀티 캐스트를 사용하는 것입니다. 그런 다음 각 서버는 멀티 캐스트 그룹에 가입하여 주요 통신용으로 구성된 고유 한 포트 번호로 응답하여 검색 데이터 그램을 수신 할 수 있습니다. 여기

일부 관련 Q & 각각 A :

C# UDP server multiple instances ipv6 same port
Listening to broadcasts when server and client are on the same machine

번째 하나 실제로 UDP 소켓 UWP 구현에서 버그을 포함하지만, 문제는 일부 양호한 디테일을 포함 이 목표를 달성하기 위해 멀티 캐스트를 사용하는 기본적인 아이디어.