2011-11-13 16 views
7

Soy incapaz de dar sentido a cómo y por qué los siguientes segmentos de código funcionan:Efecto de SO_SNDBUF

/* Now lets try to set the send buffer size to 5000 bytes */ 
    size = 5000; 
    err = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(int)); 
    if (err != 0) { 
     printf("Unable to set send buffer size, continuing with default size\n"); 
    } 

Si comprobamos el valor de la memoria de envío, es de hecho correctamente ajustado a 5000 * 2 = 10000 Sin embargo, si tratamos de enviar más que el tamaño de búfer de envío, envía todo. Por ejemplo:

n = send(sockfd, buf, 30000, 0); 

    /* Lets check how much us actually sent */ 
    printf("No. of bytes sent is %d\n", n); 

Esto muestra 30000.

Cómo hizo exactamente este trabajo? ¿El hecho de que el tamaño del búfer de envío no estaba limitado a 10000 no tuvo ningún efecto? Si lo hizo, ¿qué pasó exactamente? ¿Algún tipo de fragmentación?

ACTUALIZACIÓN: ¿Qué sucede si el zócalo está en modo sin bloqueo? He intentado lo siguiente: tamaño de buffer

  1. Cambiar a 10000 (5000 * 2) provoca 16384 bytes a enviar
  2. Cambio de tamaño del búfer a 20.000 (10.000 * 2) provoca 30000 bytes a enviar

Una vez más, ¿por qué?

Respuesta

11

El efecto de la configuración de la opción SO_SNDBUF es diferente para TCP y UDP.

  • Para UDP Esto establece el límite del tamaño del datagrama, es decir, algo más grande será descartado.
  • Para TCP, esto simplemente establece el tamaño del búfer dentro del núcleo para el zócalo dado (con algunos redondeos al límite de la página y con un límite superior).

ya que parece que está hablando TCP, el efecto que se está observando se explica por la toma de estar en modo, por lo send(2) bloquea hasta que el kernel puede aceptar la totalidad de sus datos, y/o la red bloqueando apilar los datos de forma asíncrona y empujarlo a la tarjeta de red, liberando así espacio en el búfer.

Además, TCP es un protocolo de secuencia , no conserva ninguna estructura de "mensaje". Uno send(2) puede corresponder a múltiples recv(2) s en el otro lado, y viceversa. Trátelo como byte-stream.

+0

y ¿qué sucede si el socket está en modo no bloqueante? Intenté lo siguiente: 1) Cambiar el tamaño del búfer a 10000 ocasiona que se envíen 16384 bytes 2) Cambiar el tamaño del búfer a 20000 hace que se envíen 30000 bytes Una vez más, ¿por qué? – Arun

+0

@Arun: eso es solo redondear ... ¿por qué importa eso? no debe confiar en el hecho de que el búfer es * exactamente * n bytes. el núcleo puede asignar más. –

+1

Primero, kernel no toma el tamaño de tu búfer como está, como señala @yi_H. Entonces, la pila de red funciona * asincrónicamente * con respecto a su proceso. Intente lo siguiente: comience a escribir en el zócalo, pero * no lea en el otro tamaño *.Eventualmente obtendrás un breve (el kernel acepta menos bytes luego de que lo entregues) o fallaste la escritura. –

4

SO_SNDBUF configura el búfer que utiliza la implementación de socket internamente. Si su socket no es de bloqueo, solo puede enviar hasta el tamaño configurado, si su socket está bloqueando no hay ninguna limitación para su llamada.