2012-02-02 20 views
7

Wypróbowałem sugestię od this question z bardzo małym sukcesem.Łączenie dwóch klientów UDP z jednym portem (wysyłanie i odbieranie)

Proszę ... każda pomoc zostanie bardzo doceniona!

Oto mój kod:

static void Main(string[] args) 
{ 

    IPEndPoint localpt = new IPEndPoint(IPAddress.Any, 6000); 

    UdpClient udpServer = new UdpClient(localpt); 
    udpServer.Client.SetSocketOption(
     SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 

    UdpClient udpServer2 = new UdpClient(); 
    udpServer2.Client.SetSocketOption(
     SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 

    udpServer2.Client.Bind(localpt); // <<---------- Exception here 
} 
+1

Co Wyjątkiem jest wyświetlany? –

+0

@ M.Babcock Otrzymuję komunikat wyjątku: "Podjęto próbę uzyskania dostępu do gniazda w sposób zabroniony jego uprawnieniami dostępu" – brooc

+0

Czy instancja 'udpServer' generuje ten sam wyjątek, gdy próbuje ją powiązać? –

Odpowiedz

23

Musisz ustawić opcję gniazda przed bindowaniem.

static void Main(string[] args) 
    { 
     IPEndPoint localpt = new IPEndPoint(IPAddress.Any, 6000); 

     UdpClient udpServer = new UdpClient(); 
     udpServer.Client.SetSocketOption(
      SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
     udpServer.Client.Bind(localpt); 

     UdpClient udpServer2 = new UdpClient(); 
     udpServer2.Client.SetSocketOption(
      SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 

     udpServer2.Client.Bind(localpt); // <<---------- No Exception here 

     Console.WriteLine("Finished."); 
     Console.ReadLine(); 
    } 

Albo przykład bardziej obrazowe:

static void Main(string[] args) 
    { 
     IPEndPoint localpt = new IPEndPoint(IPAddress.Loopback, 6000); 

     ThreadPool.QueueUserWorkItem(delegate 
     { 
      UdpClient udpServer = new UdpClient(); 
      udpServer.ExclusiveAddressUse = false; 
      udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
      udpServer.Client.Bind(localpt); 

      IPEndPoint inEndPoint = new IPEndPoint(IPAddress.Any, 0); 
      Console.WriteLine("Listening on " + localpt + "."); 
      byte[] buffer = udpServer.Receive(ref inEndPoint); 
      Console.WriteLine("Receive from " + inEndPoint + " " + Encoding.ASCII.GetString(buffer) + "."); 
     }); 

     Thread.Sleep(1000); 

     UdpClient udpServer2 = new UdpClient(); 
     udpServer2.ExclusiveAddressUse = false; 
     udpServer2.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
     udpServer2.Client.Bind(localpt); 

     udpServer2.Send(new byte[] { 0x41 }, 1, localpt); 

     Console.Read(); 
    } 
+0

Dziękuję bardzo !!! Pracował jak urok! – brooc

+0

Wysłałem następującą odpowiedź tutaj: http://stackoverflow.com/questions/9140450/udp-hole-punching-implemetation-in-c-sharp – brooc

+0

Dlaczego 'Bind' na' localpt' i 'Receive' na 'inEndPoint', czy jest coś innego? (Jeśli "Odbieram" na "localpt" nic nie wydaje się zepsuć) – Benjol

2

Rozejrzałem się wiadomość o błędzie, a to wyjaśnia, co to za błąd i dlaczego to się dzieje.

Oto dokładny komunikat o błędzie i przyczyna WSAEACCES 10013 (MSDN)

Permission denied.

Podjęto próbę uzyskania dostępu do gniazda w sposób zabroniony przez jego uprawnienia dostępu do domeny . Przykładem jest użycie adresu rozgłoszeniowego dla sendto bez ustawienia uprawnień rozgłaszania za pomocą setsockopt (SO_BROADCAST).

Inną możliwą przyczyną błędu WSAEACCES jest to, że gdy funkcja wiążą nazywa się (w systemie Windows NT 4.0 z dodatkiem SP4 lub nowszy), inny aplikacja, kierowca usługi lub trybu jądra jest związany z samym adres z wyłącznym dostęp. Taki wyłączny dostęp to nowa funkcja systemu Windows NT 4.0 z dodatkiem SP4 i nowszym i jest zaimplementowana przy użyciu opcji 01_SO_EXCLUSIVEADDRUSE.

+0

Dzięki, ale znalazłem już tę informację. Mój kod używa SocketOptionName.ReuseAddress, który zakładam zasadniczo SO_EXCLUSIVEADDRUSE, ale w sposób .NET. Wydaje się, że musi być jakiś inny sposób, aby to zrobić, ale nie mogę tego znaleźć. – brooc

+0

To będzie dobra łamigłówka. Myślę, że jestem na dobrej drodze. Pomogę kopiuj więcej i wypróbuj kod. Prawdopodobnie jest to coś tak prostego, że nawet najbardziej doświadczony programista go obejrzy .. – MethodMan

+0

Dzięki, patrzyłem na to od wielu dni ... Nie ma szczęścia ... To jest podobno bardzo proste zadanie ... Spróbuj uruchomić ten kod. – brooc

0

Nawet zmienia swój kod tak, że mogę przechodzić w adresie IP ja ją Wydaje się, że nie może związać się z tego samego portu i tylko jeden port może być używany tutaj ten sam komunikat o błędzie jest przykładowy kod Kiedyś swój przykład i Altered go uchwycić moje ip z mojego komputera lokalnego ..

 IPAddress ipAddress = Dns.Resolve(Dns.GetHostName()).AddressList[0]; 
     IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, 11000); 

     //IPEndPoint localpt = new IPEndPoint(ipLocalEndPoint); 

     UdpClient udpServer = new UdpClient(ipLocalEndPoint); 
     udpServer.Client.SetSocketOption(
      SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
     udpServer.Connect(ipLocalEndPoint); 
     UdpClient udpServer2 = new UdpClient(); 
     udpServer2.Client.SetSocketOption(
      SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 

     udpServer2.Client.Bind(ipLocalEndPoint); // <<---------- Exception here 

będzie produkować wyjątek z metody bind() .. przepraszam.

+0

musi być sposobem na zrobienie tego. Moim celem jest stworzenie systemu, który zawiera dziurkowanie UDP. To polega na tym, że mogę słuchać na tym samym porcie, na który wysyłam dane poprzez ... – brooc

0

Aby rozwiązać WSAEACCESS 10013 (MSDN) wyjątek w aplikacji UDP można spróbować

udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);