2012-01-17 7 views
5

Al usar sockets de bloqueo en Linux, ¿hay alguna razón para que send() devuelva menos de lo solicitado, otro que un syscall send() interrumpido pero parcialmente exitoso?¿Cuándo enviará() devolverá menos que el argumento de longitud?

Soy consciente de que posiblemente esta sea una implementación muy definida, y que probablemente sería muy peligroso confiar en ese comportamiento incluso sin controladores de señal instalados (y por lo tanto, razones para syscalls interrumpidos). Probablemente recorro la llamada de envío hasta que se complete; Sin embargo, si hubiera alguna palabra oficial sobre el asunto, podría evitar eso.

Why is it assumed that send may return with less than requested data transmitted on a blocking socket? era la misma pregunta, con resultados no concluyentes: llamadas al sistema interrumpidos se mencionan como ejemplo para un corto recuento de retorno, pero aún no está claro si un búfer TCP completa Enviar causaría un envío parcial o la send() sería simplemente bloqueará hasta hay suficiente espacio en el búfer.

Respuesta

4

En general, si el búfer de transmisión contiene algo de espacio, pero no lo suficiente para toda la solicitud de envío, enviará todo lo que pueda y luego devolverá la cantidad realmente agregada al búfer, una escritura breve.

Ahora podría argumentar que tendría más sentido bloquear (en un socket de bloqueo), pero la razón por la que no es histórico: TCP se basa en las tuberías UNIX, y esa es la forma en que funcionaron las tuberías UNIX. La razón principal es que hace que los casos de esquina (en el kernel) sean más fáciles: no tiene que preocuparse por bloquear una llamada al sistema in the middle de hacer algo; hace algo y regresa inmediatamente o no hace nada hasta que ocurre un evento (en ese momento el núcleo lo reintenta desde cero). No tiene que preocuparse por lo que sucede si alguien intenta escribir más que el tamaño máximo de búfer en una sola escritura (lo que de lo contrario podría causar un punto muerto).

+0

FWIW, la página man para 'send()' en mi cuadro Linux dice 'Cuando el mensaje no cabe en el búfer de envío del socket, send() normalmente bloquea, a menos que el socket se haya colocado en I no bloqueante Modo O En modo no bloqueante fallaría con el error EAGAIN o EWOULDBLOCK en este caso. No parece documentar que la función devuelva algo más que su argumento 'len' (o' -1' en caso de error). –

+2

Las páginas man de Linux son notoriamente vagas. Es mucho mejor que revises la página en un sistema BSD. La sección VALORES DEVUELTOS documenta que solo devuelve la cantidad de caracteres enviados sin garantía de que sea igual al número solicitado. –

Cuestiones relacionadas