que - sockets unix
programación de socket udp sin bloqueo en C: ¿qué obtengo? (3)
Creo que obtienes exactamente uno o cero datagramas. Pero no puedo respaldar esto en este momento. Tal vez alguien más podría proporcionar una buena referencia?
Editar: estoy bastante seguro de que no puedes recibir la mitad de un datagrama. O el datagrama ha llegado al buffer, o no.
Tengo un problema para entender qué recv () / recvfrom () devuelve de un socket UDP no bloqueante.
Un poco más específico y comparado con TCP (corrígeme si me equivoco):
Un socket de bloqueo (TCP o UDP) no regresará desde un recv () hasta que haya algunos datos en el búfer. Esto podría ser una cantidad de bytes (TCP) o un datagrama completo (UDP).
Un socket TCP no bloqueante devuelve EWOULDBLOCK (linux) / WSAEWOULDBLOCK (Windows) o los bytes que están actualmente en el búfer. Como los datos TCP son una secuencia, no importa cuántos bytes se devuelvan.
Ahora la pregunta:
- Un socket UDP no bloqueante también devuelve WOULDBLOCK (linux) / WSAEWOULDBLOCK (windows) si no hay datos disponibles. Pero si hay datos disponibles, ¿un socket UDP sin bloqueo devuelve solo algunos bytes, lo que podría significar que solo obtiene la mitad de un datagrama O un socket UDP siempre devuelve datagramas completos?
Editar:
Lo que quiero decir con "la mitad de un datagrama" es: ¿qué ocurre si llamo a recv () justo en el momento en que el socket recibe actualmente un datagrama? En ese momento, hay algunos bytes en el búfer, pero el datagrama aún no está completo.
Sus explicaciones y comentarios son apreciados. ¡Gracias!
Finalmente, una excusa para sacar mis libros de Stevens de mis viejos buzones de oficina.
Siempre que el búfer sea lo suficientemente grande, las funciones recv()
y recvfrom()
sockets Berkeley estándar nunca devolverán un datagrama parcial. El datagrama no está disponible para la aplicación hasta que el kernel haya recibido y reensamblado por completo el datagrama.
Curiosamente, y esto no es mucho (¿alguno?) De un problema hoy en día, otras interfaces de programación de red no se ponen de acuerdo sobre el comportamiento cuando el buffer proporcionado es demasiado pequeño:
La versión tradicional de Berkeley de la API de sockets trunca el datagrama, descartando cualquier exceso de datos. Si la aplicación se notifica depende de la versión. (4.3BSD Reno y luego puede notificar a la aplicación que el datagrama fue truncado.)
La API de sockets en SVR4 (incluido Solaris 2.x) no trunca el datagrama. Cualquier exceso de datos se devuelve en lecturas posteriores. No se notifica a la aplicación que se están realizando múltiples lecturas desde un solo datagrama UDP.
La API de TLI no descarta los datos. En su lugar, se devuelve un indicador que indica que hay más datos disponibles, y las lecturas posteriores de la aplicación devuelven el resto del datagrama.
(Stevens, TCP / IP Illustrated, Volumen 1, página 160)
Sí, UDP simplemente devuelve qué datos se transmitieron en ese datagrama. UDP no está orientado a flujos como TCP. Los datagramas son transmisiones discretas, y en realidad no están vinculados a otros datagramas de ninguna manera. Esa es la razón por la cual la opción de socket para TCP es SOCK_STREAM.
El lado bueno de esto es que puedes tener una idea de las transmisiones por separado, lo que no es realmente fácil de hacer con TCP.