Problemas de diseño - enviar segmentos de datos pequeñas a través de TCP con Winsock

Seleccione idioma Seleccione idioma
Id. de artículo: 214397 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

Resumen

Cuando necesite enviar paquetes de datos pequeñas a través de TCP, el diseño de la aplicación Winsock es especialmente importante. Un diseño que no toma en cuenta la interacción de confirmación retrasada, algoritmo de Nagle y almacenamiento en búfer de Winsock puede afectar drásticamente rendimiento. En este artículo describe estos problemas, con un par de estudios de casos y se deriva de una serie de recomendaciones para enviar paquetes de datos pequeñas eficazmente desde una aplicación de Winsock.

Más información

Fondo

Cuando una pila de TCP de Microsoft recibe un paquete de datos, un temporizador de retardo de 200 ms se ponga. Cuando finalmente se envía una confirmación, el temporizador de retardo se restablece y iniciará el retraso de 200 ms otro cuando se recibe el siguiente paquete de datos. Para aumentar la eficacia en Internet y las aplicaciones de intranet, pila de TCP de Microsoft utiliza los siguientes criterios para decidir cuándo enviar una confirmación de paquetes de datos recibidos:
  • Si se recibe el paquete de datos segundo caduque el temporizador de retardo, se envía la confirmación.
  • Si hay datos se envíe en la misma dirección como la confirmación antes de que se recibe el paquete de datos segundo y caduca el temporizador de retardo, el ACK se superpone con el segmento de datos y se envía inmediatamente.
  • Cuando caduca el temporizador de retardo, se envía la confirmación.
Para evitar congestionar la red de paquetes de datos pequeñas, pila Microsoft TCP habilita el algoritmo de Nagle de forma predeterminada, que combina un búfer de datos pequeñas de varias llamadas de envío y retrasos enviar hasta que se envía una ACK para el paquete de datos anterior se recibe desde el host remoto. Existen dos excepciones para el algoritmo de Nagle:
  • Si la pila ha fusionada un búfer de datos mayor que la unidad de transmisión máxima (MTU), un paquete de tamaño completo se envía inmediatamente sin esperar la confirmación desde el host remoto. En una red Ethernet, la MTU para TCP/IP es 1460 bytes.
  • La opción de socket TCP_NODELAY se aplica a deshabilitar el algoritmo de Nagle para que se entregan los paquetes de datos pequeñas en el host remoto sin retraso.
Para optimizar el rendimiento en el nivel de aplicación, Winsock copias búferes de datos de aplicación envían llamadas a un búfer de núcleo de Winsock. A continuación, la pila utiliza su propio heurística (como algoritmo de Nagle) para determinar cuándo colocar realmente el paquete en la conexión. Puede cambiar la cantidad de búfer del núcleo de Winsock asignado al socket con la opción de SO_SNDBUF (es 8 KB de forma predeterminada). Si es necesario, Winsock puede búfer significativamente más el SO_SNDBUF tamaño del búfer. En la mayoría de los casos, la finalización de envío en la aplicación sólo indica el búfer de datos en una aplicación envía la llamada se copia en el búfer del núcleo de Winsock y no indica que los datos ha alcanzado el medio de red. La única excepción es cuando deshabilita el búfer de Winsock estableciendo SO_SNDBUF en 0.

Winsock utiliza las siguientes reglas para indicar una finalización de envío a la aplicación (dependiendo de cómo se invoca el envío, la notificación de finalización podría ser la función de devolución de llamada de bloqueo, señalización un evento o llamar a una función de notificación etc.):
  • Si el socket está aún dentro de la cuota SO_SNDBUF, Winsock copia los datos desde el envío de aplicación y indica la finalización de envío a la aplicación.
  • Si el socket está más allá de la cuota SO_SNDBUF y hay sólo un envío previamente almacenados en búfer aún el búfer de pila del núcleo, Winsock copia los datos desde el envío de aplicación e indica la finalización de envío a la aplicación.
  • Si el socket está más allá de la cuota SO_SNDBUF y hay más de un búfer anteriormente enviar el búfer de pila del núcleo, Winsock copia los datos desde el envío de la aplicación. Winsock no indica la finalización de envío a la aplicación hasta que la pila completa suficiente envía para poner el socket volver dentro de cuota SO_SNDBUF o sólo una condición de envío pendiente.

Caso práctico 1

Introducción:

Un cliente Winsock TCP necesita enviar 10000 registros a un servidor TCP Winsock para almacenar en una base de datos. El tamaño de los registros varía de 20 bytes a 100 bytes. Para simplificar la lógica de aplicación, el diseño es como sigue:
  • El cliente no sólo enviar bloqueo. El servidor no sólo recv de bloqueo.
  • El socket de cliente establece la SO_SNDBUF en 0 para que sale cada registro en un segmento de datos único.
  • El servidor llama a la recepción de un bucle. El búfer registrado en recv es 200 bytes para que cada registro se puede recibir en una recepción llamada.

Rendimiento:

Durante las pruebas, el desarrollador busca que el cliente no pudo enviar sólo cinco registros por segundo al servidor. El total de 10000 registros, máximo en KB 976 bytes de datos (10000 * 100 / 1024), se realiza en mitad más de una hora de enviar al servidor.

Análisis:

Porque el cliente no establecida la opción TCP_NODELAY, el algoritmo de Nagle obliga a la pila TCP para esperar una confirmación antes de pueda enviar otro paquete en el cable. Sin embargo, el cliente ha deshabilitado el búfer de Winsock estableciendo 0 en la opción de SO_SNDBUF. Por lo tanto, en el 10000 enviar llama tienen que enviarse y ACK'ed individualmente. Cada ACK es ms-200 retrasadas porque ocurre lo siguiente en la pila TCP del servidor:
  • Cuando el servidor obtiene un paquete, se ponga su temporizador de retardo de 200 ms.
  • El servidor no es necesario enviar nada, por lo que no se superpone el ACK.
  • El cliente no enviará otro paquete a menos que se confirma el paquete anterior.
  • Caduca el temporizador de retardo en el servidor y se devolvió el ACK.

Cómo mejorar el:

Hay dos problemas con este diseño. En primer lugar, es el problema del temporizador de retardo. El cliente debe poder enviar dos paquetes al servidor dentro de 200 ms. como el cliente utiliza el algoritmo de Nagle de forma predeterminada, debe, utilice el búfer de Winsock predeterminado y no establece SO_SNDBUF en 0. Una vez que la pila TCP ha fusionada un búfer mayor que la unidad de transmisión máxima (MTU), un paquete de tamaño completo se envía inmediatamente sin esperar la confirmación desde el host remoto.

En segundo lugar, este diseño llama a un envío para cada registro de dicho tamaño pequeño. Enviar esta pequeña de un tamaño no es muy eficaz. En este caso, el desarrollador que desee rellenar cada registro de 100 bytes y enviar registros de 80 a la vez desde un cliente llamada. Para permitir que el servidor sabe cuántos registros se enviarán en total, el cliente que desee iniciar la comunicación con un encabezado de tamaño de corrección que contiene el número de registros que siga.

Caso práctico 2

Introducción:

Una aplicación de cliente TCP Winsock abre dos conexiones con una aplicación de servidor TCP Winsock proporciona servicio de cotizaciones. La primera conexión se utiliza como un canal de comandos para enviar el símbolo de cotización al servidor. La segunda conexión se utiliza como un canal de datos para recibir la cotización. Una vez establecidas las dos conexiones, el cliente envía un símbolo de cotización al servidor mediante el canal de comandos y espera a que la cotización de bolsa regresar a través del canal de datos. La siguiente solicitud de símbolo de cotización envía al servidor sólo después de la primera cotización se ha recibido. El cliente y el servidor no debe establecer la opción SO_SNDBUF y TCP_NODELAY.

Rendimiento:

Durante las pruebas, el desarrollador busca que el cliente sólo puede obtener cinco ofertas por segundo.

Análisis:

Este diseño sólo permite una solicitud de cotización de acciones pendientes al mismo tiempo. El primer símbolo stock se envía al servidor mediante el canal de comandos (conexión) y una respuesta se envía inmediatamente volver desde el servidor al cliente a través del canal de datos (conexión). A continuación, el cliente envía inmediatamente la segunda solicitud símbolo de cotización y el envío se devuelve inmediatamente como el búfer de solicitud en la llamada de envío se copia en el búfer del núcleo de Winsock. Sin embargo, la pila TCP de cliente no puede enviar la solicitud desde su búfer núcleo inmediatamente porque la primera enviar sobre el canal de comandos no reconocido todavía. Después de 200-ms retrasar temporizador en el canal de comandos de servidor caduca, la confirmación de la primera solicitud de símbolo regresa al cliente. A continuación, la segunda solicitud de oferta correctamente se envía al servidor después se retrase para la cotización para el segundo símbolo stock regresa inmediatamente a través del canal datos porque, en este momento, ha caducado el temporizador de retardo en el canal de datos de cliente de ms. 200. El servidor recibe una confirmación para la respuesta anterior de la oferta. (Recuerde que el cliente puede no enviar una segunda solicitud cotizaciones para 200-ms, así dar tiempo para el temporizador de retardo en el cliente para caducar y enviar una confirmación al servidor). Como resultado, el cliente obtiene la segunda respuesta de oferta y puede emitir otra solicitud de oferta, está sujeta al mismo ciclo.

Cómo mejorar el:

El diseño de conexión de dos (canal) no es necesario aquí. Si utiliza sólo una conexión para la solicitud de cotización y la respuesta, se puede superpuesto en la respuesta de oferta y volver inmediatamente el ACK para la solicitud de oferta. Para mejorar aún más el rendimiento, el cliente podría "multiplexación" varias solicitudes de cotizaciones en una llamada de envío al servidor y el servidor podría también "multiplexación" varias respuestas de oferta en una llamada de envío al cliente. Si el diseño de dos canal unidireccional es realmente necesario por algún motivo, ambos lados deben establecer la opción TCP_NODELAY para que se pueden enviar paquetes pequeños inmediatamente sin tener que esperar una confirmación ACK para el paquete anterior.

Recomendaciones:

Mientras se crea estos dos casos prácticos, ayudan a ilustrar algunos escenarios peores. Cuando se diseña una aplicación implica muchos datos pequeño segmento envía y recvs, debería considerar las siguientes directrices:
  • Si los segmentos de datos no tiempo crítica, la aplicación debe unión en un bloque de datos mayor para pasar a una llamada de envío. Como el búfer de envío es probable que se copien en el búfer del núcleo de Winsock, el búfer no debe ser demasiado grande. Un poco menos de 8 KB normalmente es eficaz. Siempre que el núcleo Winsock Obtiene un bloque mayor que la MTU, enviará varios paquetes de tamaño completo y un último paquete con lo que queda. No se llegará al lado de envío, excepto el último paquete por el temporizador de retardo de 200 ms. El último paquete si ocurre que un paquete con numeración impar, es aún sujeta el algoritmo de confirmación retrasada. Si la pila final envío obtiene otro bloque mayor que la MTU, todavía puede omitir el algoritmo de Nagle.
  • Si es posible, evite las conexiones de socket con el flujo de datos unidireccional. Las comunicaciones a través de sockets unidireccionales son más fácilmente afectados por el este y retrasan algoritmos de confirmación. Si la comunicación sigue una solicitud y un flujo de respuesta, debe utilizar un socket único para envía y recvs que puede se superpone el ACK en la respuesta.
  • Si deben de los segmentos de datos pequeñas se envíen inmediatamente, establezca opción de TCP_NODELAY en el extremo emisor.
  • A menos que desee garantizar que se envía un paquete en la conexión cuando una finalización de envío se indica mediante Winsock, no debe establecer la SO_SNDBUF a cero. De hecho, el búfer de 8 KB predeterminado se ha determinado heurísticamente que funcionan bien para la mayoría de las situaciones y debería no cambiarlo a menos que haya probado que la nueva configuración de búfer de Winsock proporciona mejor rendimiento sea el predeterminado. Además, establecer SO_SNDBUF a cero principalmente es beneficioso para las aplicaciones que se de forma masiva transferencia de datos. Incluso entonces, para mejorar la eficacia máxima debe usarlo junto con el doble búfer (más de un envío pendiente en cualquier momento) y E/s superpuesta.
  • Si la entrega de datos no tiene que ser garantizada, utilice UDP.

Referencias

Para obtener más información acerca de confirmación retrasada y el algoritmo de Nagle, consulte el siguiente:

Braden, r. [1989], RFC 1122, Requirements for Internet Hosts--Communication Layers, tareas de ingeniería de Internet Force.

Propiedades

Id. de artículo: 214397 - Última revisión: lunes, 11 de julio de 2005 - Versión: 3.1
La información de este artículo se refiere a:
  • Microsoft Platform Software Development Kit-January 2000 Edition
Palabras clave: 
kbmt kbdswnet2003swept kbapi kbinfo kbip kbnetwork kbwinsock KB214397 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 214397

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com