2012-03-23 23 views
6

Por favor, consulte mi pregunta anterior para el código de muestra Sockets: sometimes (rarely) packets are lost during receiving¿debo usar while (true) para recibir datos de Socket?

Necesito recibir datos siempre desde el socket de multidifusión UDP. Esta es una comunicación unidireccional. Solo necesito escuchar nuevos datos y procesarlos lo antes posible.

¿Debo utilizar while(true)? No me gusta while(true) porque en mi opinión esto produce mucho trabajo extra para el procesador. Probablemente C# ofrece otras técnicas de devolución de llamada o algo así.

+1

¿Qué llamada específica está utilizando para escuchar nuevos paquetes? hay muchas formas en que se puede hacer, y es importante. Además: ¿cuál es la naturaleza de la aplicación? ¿Cuántas transmisiones está escuchando también? si solo esta (o algunas), entonces un hilo dedicado y llamadas de lectura de bloqueo probablemente no sean un problema.Para un servidor dedicado con docenas o cientos o miles de conexiones, definitivamente querrá usar devolución de llamada IO o Socket.Select. –

+0

@MarcGravell Debo escuchar varias tomas (de 2 a 6), estoy usando hilo dedicado para cada Socket. Recibo ~ 2000 paquetes por segundo en cada socket – javapowered

Respuesta

3

2 a 6 tomas de corriente (comentarios) es, probablemente, en el lugar interesante donde ya sea bloqueando o asíncrono IO no tendrán ningún problema, ya que no están inundando la máquina con hilos. Con 2000 paquetes por segundo, parece que hay mucho para mantener los hilos ocupados. No necesita preocuparse por while(true) desde una perspectiva de rendimiento, ya que el método Receive se bloqueará hasta que los datos estén disponibles, por lo que es nunca haciendo un hot-loop de no hacer nada. ¡Sin embargo! En lo personal, desde el punto de vista estético, estoy de acuerdo while(true) es una mancha innecesaria, por lo que si usted está utilizando el enfoque de bloqueo, tal vez considero:

int bytesRead; 
while((bytesRead = socket.Receive(buffer)) > 0) { 
    // process bytesRead from buffer 
} 

que salir limpiamente cuando se cierra el socket.

Usted También puede hacer esto con cualquiera de las BeginReceive y Socket.ReceiveAsync métodos, que no utiliza una llamada de bloqueo, sino que utiliza ya sea un evento o de devolución de llamada. Estos son particularmente útiles cuando se manejan muchas conexiones.

Personalmente, lo que tiendo a hacer es usar Socket.Available; si esto es positivo, entonces hay datos almacenados en búfer y listos para consumir, por lo que se puede usar un simple Receive para obtener esos datos de manera inmediata y sin un cambio de contexto. Si es cero, entonces no hay datos disponibles en actualmente, por lo que una llamada asincrónica puede ser más apropiada. Esto equilibra los cambios de contexto con llamadas directas. Tenga en cuenta que el enfoque ReceiveAsync ha esta construida en también, a través del valor de retorno de ReceiveAsync (que es true si la operación es incompleta, y una devolución de llamada se invoca después - y false si la operación es ya completa, y sin se invocará la devolución de llamada).

+0

gracias Marc. Supongo que mi tarea (recibir datos de multidifusión desde varios sockets UDP) es tan general que debería haber una solución "ideal". Esto es lo que la gente necesita hacer para ver ip tv o radio y para recibir datos de "bolsa" en mi caso. Estoy seguro de que el ejemplo de código "recomendado para usar" debería estar en algún lugar probablemente incluso en algún lugar de msdn. Probablemente alguien pueda vincular tal muestra de código ... – javapowered

+0

También probablemente sepa por qué pierdo mi marca de identificación :(vea mi pregunta relacionada – javapowered

+1

@javapowered er sí ... ** porque está usando UDP **. Eso es normal. –

1

La mejor manera para la programación de sockets es utilizando sus equivalentes Async. En lugar de ejecutar bucles infinitos, debe llamar a BeginReceive y establecer su método de devolución de llamada que se activará una vez completada la transmisión. De esta forma, conservará el control de su aplicación y utilizará muchos menos recursos.

Referencia: http://msdn.microsoft.com/en-us/library/bbx2eya8.aspx#Y0

+1

La "mejor" manera casi siempre depende de * poco * en el contexto ... –

+0

No tiene nada que objetar a eso. Será más preciso en mis respuestas a partir de ahora :) –

0

El método asincrónico es la mejor solución.

Sin embargo, en este caso si usa while (verdadero) que contiene socket.Receive (buf) no hay trabajo adicional para el procesador porque si no establece un tiempo de espera el bloque sockect bloquea el ciclo hasta que lleguen los datos.

Cuestiones relacionadas