2010-02-19 11 views
6

La página del manual función de biblioteca recv() mencionan que:caso cuando el bloqueo de recv() devuelve menos de bytes solicitado

Devuelve el número de bytes recibidos. Por lo general, devuelve todos los datos disponibles, hasta la cantidad solicitada, en lugar de esperar el recibo de la cantidad total solicitada.

Si estamos usando el bloqueo de recv() llamada y solicitado para 100 bytes:

recv(sockDesc, buffer, size, 0); /* Where size is 100. */ 

y sólo 50 bytes son enviados por el servidor entonces este recv() se bloquea hasta 100 bytes están disponibles, o devolverá recibir 50 bytes.

El escenario podría ser que:

  • servidor se bloquea después de sendign sólo 50 bytes

  • mal diseño del protocolo, donde servidor sólo envía 50 bytes mientras el cliente está esperando 100 y servidor también está esperando la respuesta del cliente (es decir, la conexión de conexión de socket no ha sido iniciada por el servidor en el que volverá recv)

Me interesa Li plataforma nux/Solaris. No tengo el entorno de desarrollo para verificarlo yo mismo.

Respuesta

13

recv volverá cuando hay datos en las memorias intermedias internas de volver. No esperará hasta que haya 100 bytes si solicita 100 bytes.

Si va a enviar "mensajes" de 100 bytes, recuerde que TCP no proporciona mensajes, solo es una secuencia. Si está tratando con mensajes de aplicación, debe manejar eso en la capa de aplicación ya que TCP no lo hará.

Hay muchas, muchas condiciones en las que una llamada a send() de 100 bytes podría no leerse completamente en el otro extremo con solo una llamada recv al llamar a recv (..., 100); He aquí sólo pocos ejemplos:

  • La pila TCP emisor decidió agrupar juntos 15 llamadas de escritura, y la MTU pasó a ser 1460, el cual - en función de sincronización de los datos llegados podría provocar que los clientes primeros 14 llamadas para buscar 100 bytes y la 15. llamada para buscar 60 bytes; los últimos 40 bytes llegarán la próxima vez que llame a recv().(Pero si llama a recv con un búfer de 100, puede obtener los últimos 40 bytes del "mensaje" de la aplicación anterior y los primeros 60 bytes del siguiente mensaje)

  • Los buffers del remitente están llenos, tal vez el lector es lento o la red está congestionada En algún momento, los datos podrían pasar y mientras vaciaban los almacenamientos intermedios, el último fragmento de datos no era un múltiplo de 100.

  • Los almacenamientos intermedios del receptor están llenos, mientras que la aplicación recv() esa información, el último trozo que el pull-up es solo parcial ya que los 100 bytes enteros de ese mensaje no se ajustaban a los buffers.

Muchos de estos escenarios son bastante difíciles de probar, sobre todo en una LAN en la que puede que no tenga una gran cantidad de congestión o pérdida de paquetes - las cosas podrían ser diferentes a medida que la rampa encima y abajo de la velocidad a la que se envían los mensajes/producido.

De todos modos. Si desea leer 100 bytes desde un socket, usar algo como

int 
readn(int f, void *av, int n) 
{ 
    char *a; 
    int m, t; 

    a = av; 
    t = 0; 
    while(t < n){ 
     m = read(f, a+t, n-t); 
     if(m <= 0){ 
      if(t == 0) 
       return m; 
      break; 
     } 
     t += m; 
    } 
    return t; 
} 

...

if(readn(mysocket,buffer,BUFFER_SZ) != BUFFER_SZ) { 
    //something really bad is going on. 

} 
+0

Gracias por la explicación detallada. ¿Confirmando si esto también es válido para la llamada * blocking * recv()? (es decir, retorno de recv() con bytes inferiores a los solicitados) – Adil

+0

Sí, esto es cierto para una llamada de bloqueo de recepción. – nos

2

Si usted lee la cita precisamente, el escenario más común es:

  • la toma está recibiendo datos. Eso 100 bytes tomará algo de tiempo.
  • se realiza la llamada a recv().
    • Si hay más de 0 bytes en el búfer, recv() devuelve lo que está disponible y no espera.
    • Si bien hay 0 bytes disponibles, bloquea y la granularidad del sistema de subprocesos determina cuánto tiempo es eso.
+0

Gracias, significa que si se emite un bloqueo de recepción() y los datos están disponibles (menos de lo solicitado), se devolverá con los datos que estén disponibles. ¿derecho? – Adil

7

El comportamiento está determinado por dos cosas. La marca de agua baja recv y si pasa la bandera MSG_WAITALL o no. Si pasa este indicador, la llamada se bloqueará hasta que se reciba el número solicitado de bytes, incluso si el servidor falla. De lo contrario, regresa tan pronto como al menos SO_RCVLOWAT bytes están disponibles en el búfer de recepción del zócalo.

SO_RCVLOWAT

establece el número mínimo de bytes a proceso para operaciones de entrada socket. El valor predeterminado para SO_RCVLOWAT es 1. Si SO_RCVLOWAT se establece en un valor mayor, bloqueando recibir llamadas normalmente espere hasta que hayan recibido el menor del valor de marca de agua baja o la cantidad solicitada. (Pueden devolver por debajo de la marca de agua baja si se produce un error , se capta una señal o el tipo de datos a continuación en la cola de recepción es diferente al devuelto, por ejemplo, datos fuera de banda). Esta opción toma un valor int. Tenga en cuenta que no todas las implementaciones permiten configurar esta opción en .

+0

SO_RCVLOWAT es la opción de socket. si no hemos configurado ninguna opción de socket y no se pasa ninguna bandera a recv(), y se emite el bloqueo de la llamada a recv(), ¿esperará todos los bytes solicitados? (La operación de cierre del socket tampoco se ha initaizado) – Adil

+1

En la situación que describa en su publicación, devolverá 50 bytes. ** No ** esperará los 100 bytes completos a menos que pase el indicador 'MSG_WAITALL' a' recv'. –

Cuestiones relacionadas