2010-09-02 4 views
7

Voglio utilizzare UDP-Sockets per il mio XNA-Networkgame. E ora sto cercando di codificare un Listenerthread affidabile, ma ci sono alcuni problemi.C#: Listener UDP Thread

Se utilizzo socket. Ricevuto, aspetterà un pacchetto. Questo va bene per il mio Listenerthread. mio thread ha un ciclo while in questo modo:

while(Listen == true) 
{ 
    socket.Receive(...); 
} 

Ma se io scambiare la Listen-Flag a false (se voglio smettere di ascoltare), sarà attaccato nell'ultima .Receive().

Poi ho esaminato i metodi .BeginReceive(). Chiamerà un metodo se un pacchetto è arrivato. Ma per ricevere i dati devo usare .EndReceive() e questo è il punto in cui ho un problema. Voglio ancora ascoltare i pacchetti e non smettere di ascoltare se arriva un pacchetto.

Quindi uso ancora la versione di blocco con ".Receive()". Potrei forzare l'ascolto del thread per cancellare chiamando: Thread.abort(), ma questo non va bene.

Attualmente mi testare se i dati sono disponibili:

while(Listen == true) 
{ 
    if(socket.Available > 0) 
    { 
     socket.Receive(...); 
    } 
} 

ma credo che questo non è il modo migliore ... Se poco dopo il caso-clausola di un altro thread sta chiamando socket.Receive (..) rimarrà di nuovo non intenzionale. Non c'è modo di annullare il metodo .Receive (..)? Ho provato a impostare un timeout, ma se .Ricevi timeout, verrà generata un'eccezione ...

Voglio un semplice thread di ascolto udp, posso fermarmi con garbo. :-) In MSDN non ho trovato un esempio listener che stia ascoltando più di un pacchetto. Come gestire questo programmatore?

+0

"Se poco dopo il caso-clausola di un altro thread sta chiamando socket.Receive (..)" - questo sembra implicare che ci sono più thread di lettura dalla stessa presa di corrente? – Ragoczy

+0

No, non lo faccio. Ma è possibile e voglio evitarlo :-) – user437899

+1

Quando sei pronto per interrompere l'ascolto, chiudi il socket. Il metodo di blocco 'Receive()' uscirà con una 'SocketException' che dovrai catturare. –

risposta

9

Contrassegnare il flag Listen come volatile, in modo che le modifiche possano essere visibili tra i thread.

public volatile bool Listen{get; set;} 

Gestire le opportune eccezioni in tuo thread:

Thread listener = new Thread(()=> 
{ 
    while(Listen == true) 
    { 
     try 
     { 
      socket.Receive(); 
     } 
     catch(ThreadInterruptException) 
     { 
      break; // exit the while loop 
     } 
     catch(SocketException) 
     { 
      break; // exit the while loop 
     } 
    } 
}); 
listener.IsBackground = true; 
listener.Start(); 

Nel codice in cui si sta passando la bandiera a Listenfalse si sia chiuso la presa o si interrompe il filo:

Listen = false; 

socket.Shutdown(SocketShutdown.Both); 
socket.Close(); 
// 
// OR 
// 
listener.Interrupt(); 
1

Grazie Lirik e Matt Davis. Funziona bene, ma va bene usare Eccezioni per questo? Ho imparato che solo le eccezioni dovrebbero essere lanciate se succede qualcosa di brutto/inaspettato. (per fermare il metodo di blocco è inteso :-))

Ho gestito l'eccezione come questa. Cerco il codice di errore e quindi interrompo il ciclo.

   try 
       { 
        broadcastSocket.ReceiveFrom(returnData, ref ep); 

        //... 
       } 
       catch (SocketException ex) 
       { 
        if (ex.ErrorCode == 10004) 
        { 
         break; 
        } 
       } 

Perché devo usare

socket.Shutdown(SocketShutdown.Both); 

prima

socket.Close(); 

Will .Serrare() non spegnere la presa pure?

E se voglio usare di nuovo il socket, esiste un metodo di "Restart" o devo creare una nuova istanza di socket?

Saluti user437899

+0

È perfettamente necessario utilizzare un'eccezione per uscire da una chiamata bloccante, quindi non temere l'eccezione! Arresto interrompe l'invio e la ricezione, ma Chiudi "spegne" il socket ma in modo forzato. Se si desidera riutilizzare il socket, chiamare Disconnect invece di Close. – Kiril