As O.K.W. dice, múltiples llamadas pendientes BeginSend
funcionarán bien. Sin embargo, probablemente DEBES tener en cuenta algunas cosas.
En primer lugar, si se trata de un socket TCP, esta sigue siendo una única secuencia de datos de igual a igual.
En segundo lugar si todas las llamadas BeginSend
se producen en el mismo hilo, el resultado será que el par recibe los datos en el orden de las llamadas. Si sus llamadas BeginSend
se producen a partir de diferentes hilos, entonces los datos podrían llegar en cualquier orden, ya que es probable que exista una condición de carrera entre cada uno de los envíos. Esto puede o no tener importancia para usted (depende de si está enviando mensajes discretos y completos con cada envío o no).
En tercer lugar, si usa TCP y envía más rápido de lo que puede recibir el código en el otro extremo del socket, entonces puede llenar la ventana TCP y las pilas TCP comenzarán a realizar control de flujo en su flujo de datos. Si continúa emitiendo llamadas BeginSend
, PUEDE terminar en una situación en la que las devoluciones de llamada tardan más y más en llamarse, ya que la pila TCP en su servidor pone en cola los datos para enviar (solo recibe la devolución una vez que los datos han sido enviados y El control de flujo basado en la ventana TCP evitará que se envíen nuevos datos hasta que la ventana TCP ya no esté "llena", es decir, que el par haya enviado ACK para algunos de los datos que son in flight
).
Puede entrar en una situación en la que esté agotando recursos en la máquina de envío de manera incontrolable (emite un BeginSend
y no tiene idea de cuándo se completará y cada envío utiliza memoria para el búfer que se envía y potencialmente non-paged pool
abajo en el código de Winsock ... Non-paged pool
es un recurso de todo el sistema y es bastante escaso en sistemas operativos anteriores a Vista y algunos controladores de mal comportamiento pueden mostrar la casilla azul si non-paged pool
está bajo o agotado. Además, puede estar bloqueando páginas de memoria en la memoria y hay otro límite amplio del sistema en el número de páginas de memoria bloqueadas.
Debido a estos problemas, generalmente es mejor implementar su propio flujo de nivel de protocolo control que limita el número de llamadas BeginSend
que pueden estar pendientes en cualquier momento (utilizando un nivel de protocolo ACK, tal vez) o para trabajar con el control de flujo de la ventana TCP y usar la finalización de un envío pendiente para emitir un nuevo envío y puede Ponga los datos en cola para enviar en su propia memoria y tenga un control total sobre los recursos utilizados y lo que hace si pone en cola "demasiados" datos. Ver mi blog aquí para obtener más detalles sobre esto: http://www.serverframework.com/asynchronousevents/2011/06/tcp-flow-control-and-asynchronous-writes.html
Ver esta respuesta: what happens when tcp/udp server is publishing faster than client is consuming? para obtener más información sobre el control de flujo de ventana TCP y lo que sucede con los que superpuesto de E/S (en C++ tierra) cuando usted lo ignora y emisión demasiados envíos superpuestos ...
En resumen, la publicación de múltiples llamadas simultáneas BeginSend
es la forma óptima de flujo de datos TCP, pero debe asegurarse de no enviar "demasiado rápido" ya que una vez que consume recursos en un manera que no puede controlar y que es potencialmente fatal para la máquina en la que se está ejecutando su código. Por lo tanto, no permita que haya un número ilimitado de llamadas BeginSend
sobresalientes e, idealmente, perfile la casilla para asegurarse de no estar agotando los recursos de todo el sistema.
@Lens, esa es una buena +1 –
@lens: Tengo ventanas incorporadas en el protocolo que estoy enviando (smpp) para que nunca sean una cuestión de enviar demasiado rápido. Sin embargo, el punto fuera de orden que menciones sería un problema. – Toad
@Len, mal escrito su nombre en mi comentario anterior, mi disculpa :) –