2010-09-02 14 views
7

Quiero usar Sockets UDP para mi XNA-Networkgame. Y ahora estoy intentando codificar una Listenerthread confiable, pero hay algunos problemas.C#: Oído de escucha UDP

Si uso socket.Receive esperará hasta que un paquete. Esto está bien para mi Listenerthread. Mi hilo tiene un tiempo de ciclo de esta manera:

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

Pero si intercambiar los Listen-bandera a falso (si quiero dejar de escuchar), será atrapado en el último .Receive().

Luego miré el Methodes .BeginReceive(). Llamará a un método si llegó un paquete. Pero para recibir los datos tengo que usar .EndReceive() y ese es el punto con el que tengo un problema. Quiero seguir escuchando los paquetes y no dejo de escuchar si llega un paquete.

Así que todavía uso la versión de bloqueo con ".Receive()". Pude forzar que el hilo de escucha se cancele al llamar: Thread.abort(), pero esto no es bueno.

Actualmente me prueba si se dispone de datos:

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

pero creo que esto no es la mejor manera ... Si poco después de la cláusula si un otro hilo está llamando socket.Receive (..) se bloqueará involuntariamente de nuevo. ¿No hay forma de cancelar el método .Receive (..)? He intentado establecer un tiempo de espera, pero si .Recibo tiempo de espera, arrojará una excepción ...

Quiero un hilo udp de escucha simple, puedo parar con gracia. :-) En MSDN no encontré un listener-example que esté escuchando más de un paquete. ¿Cómo manejar otros programadores esto?

+0

"Si poco después de la cláusula si un otro hilo está llamando socket.Receive (..)" - Esto parece implicar que hay múltiples hilos de lectura desde el mismo socket? – Ragoczy

+0

No, no hago eso. Pero es posible y quiero evitar eso :-) – user437899

+1

Cuando esté listo para dejar de escuchar, cierre el socket. El método de bloqueo 'Receive()' saldrá con 'SocketException' que necesitará capturar. –

Respuesta

9

Marque la bandera Listen como volátil, por lo que los cambios pueden ser visibles entre los hilos.

public volatile bool Listen{get; set;} 

Manejar las excepciones apropiadas en el hilo:

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

En el código en el que está cambiando la bandera Listen a false que o bien cerrar la toma o se interrumpe el hilo:

Listen = false; 

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

Gracias Lirik y Matt Davis. Funciona bien, pero ¿está bien usar Excepciones para esto? He aprendido que las excepciones solo se deben lanzar si ocurre algo malo/inesperado. (para detener el metodo de bloqueo se pretende :-))

He manejado la excepción de esta manera. Busco el código de error y luego rompo el ciclo.

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

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

¿Por qué tengo que usar

socket.Shutdown(SocketShutdown.Both); 

antes

socket.Close(); 

Will .close() No apague la toma así?

Y si quiero utilizar el socket de nuevo, ¿hay un "Restart" -metodo y debo crear una nueva instancia de socket?

Saludos user437899

+0

Está perfectamente bien usar una excepción para salir de una llamada de bloqueo, ¡así que no temas la Excepción! El apagado detiene el envío y la recepción, pero Cerrar "apagará" el socket, pero de manera contundente. Si desea reutilizar el socket, llame a Disconnect en lugar de Close. – Kiril