2012-02-02 9 views
7

Ho provato il suggerimento dallo this question con scarso successo.Collegamento di due client UDP a una porta (Invia e ricevi)

Per favore ... qualsiasi aiuto sarà molto apprezzato!

Ecco il mio codice:

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

Cosa eccezione vuoi arrivare? –

+0

@ M.Babcock Il messaggio di eccezione che ottengo è: "Si è tentato di accedere a un socket in un modo vietato dalle autorizzazioni di accesso" – brooc

+0

L'istanza di 'udpServer' genera la stessa eccezione quando si tenta di collegarla? –

risposta

23

È necessario impostare l'opzione socket prima del binding.

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(); 
    } 

O un esempio più illustrativo:

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

Grazie mille !!! Ha funzionato come un fascino! – brooc

+0

Ho postato una domanda di follow-up qui: http://stackoverflow.com/questions/9140450/udp-hole-punching-implemetation-in-c-sharp – brooc

+0

Perché si 'Bind' su' localpt' e 'Receive' su 'inEndPoint', c'è un altro? (Se I 'Receive' su' localpt' non sembra che nulla si interrompa) – Benjol

2

ho guardato il vostro messaggio di errore e questo spiega cosa l'errore è e perché sta accadendo.

Ecco il messaggio di errore esatto e ragione WSAEACCES 10013 (MSDN)

Autorizzazione negata.

Si è tentato di accedere a un socket in un modo vietato dalle sue autorizzazioni di accesso . Un esempio è l'utilizzo di un indirizzo broadcast per sendto senza l'autorizzazione broadcast impostata utilizzando setsockopt (SO_BROADCAST).

Un'altra possibile ragione per l'errore WSAEACCES è che quando la funzione bind viene chiamata (su Windows NT 4.0 con SP4 e versioni successive), un'altra applicazione, driver di servizio o in modalità kernel è destinato allo stesso indirizzo con l'esclusiva accesso. Tale accesso esclusivo è una nuova funzionalità di Windows NT 4.0 con SP4 e versioni successive e viene implementata utilizzando l'opzione 01_2_SO_EXCLUSIVEADDRUSE.

+0

Grazie, ma ho già trovato queste informazioni. Il mio codice utilizza SocketOptionName.ReuseAddress che presumo sia essenzialmente SO_EXCLUSIVEADDRUSE ma in modo .NET. Sembra che ci sia bisogno di un altro modo per farlo, ma non riesco a trovarlo – brooc

+0

Questo sarà un buon puzzle .. Immagino di essere sulla buona strada. Ti aiuterò a scavare di più e provare il codice pure ... è probabilmente qualcosa di così semplice che anche il programmatore più esperto lo guarderebbe .. – MethodMan

+0

Grazie, ho guardato questo per giorni ... Nessuna fortuna ... Questo è presumibilmente un molto cosa semplice da fare ... Si prega di provare a eseguire questo codice. – brooc

0

Anche cambiando il codice in modo che io possa passare un indirizzo IP mi viene lo stesso messaggio di errore sembra che non è possibile associare alla stessa porta e una sola porta può essere utilizzata Ecco il codice di esempio ho usato il vostro esempio e alterato per catturare il mio IP dalla mia macchina locale ..

 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 

questo produrrà l'eccezione del metodo Bind() .. sorry.

+0

Là deve essere un modo per farlo. Il mio obiettivo è creare un sistema che incorpori la perforazione UDP. Questo dipende dal fatto che posso ascoltare sulla stessa porta che sto inviando i dati attraverso ... – brooc

0

Per risolvere WSAEACCESS 10013 (MSDN) eccezione nell'applicazione UDP si può provare

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