No veo tu código, tendré que adivinar.
La razón por la que obtiene una ventana Cero en TCP es porque no hay espacio en el búfer recv del receptor.
Existen varias formas de que esto ocurra. Una causa común de este problema es cuando está enviando a través de una LAN u otra conexión de red relativamente rápida y una computadora es significativamente más rápida que la otra computadora. Como un ejemplo extremo, digamos que tiene una computadora 3Ghz que envía lo más rápido posible a través de un Gigabit Ethernet a otra máquina que tiene una CPU de 1Ghz. Como el emisor puede enviar mucho más rápido de lo que el receptor puede leer, el búfer de recepción del receptor se llenará y la pila de TCP anunciará una ventana Cero al remitente.
Ahora esto puede causar problemas tanto en el lado de envío como en el lado de recepción si no están preparados para hacer frente a esto. En el lado de envío, esto puede ocasionar que el buffer de envío se llene y que las llamadas se envíen a bloquearse o fallar si está usando E/S sin bloqueo. En cuanto a la recepción, podría estar pasando tanto tiempo en E/S que la aplicación no tiene la oportunidad de procesar ninguno de sus datos y dar la apariencia de estar encerrado.
Editar
De algunas de sus respuestas y código Parece que su aplicación es de un solo subproceso y que está tratando de hacer no bloqueante envía por alguna razón. Supongo que está configurando el socket como no bloqueante en alguna otra parte del código.
En general, diría que esta no es una buena idea. Idealmente, si le preocupa que su aplicación se cuelgue en un send(2)
, debe establecer un tiempo de espera prolongado en el socket usando setsockopt
y usar un hilo separado para el envío real.
Ver socket(7):
SO_RCVTIMEO y SO_SNDTIMEO Especifique la recepción o el envío de los tiempos de espera hasta que informar de un error. El parámetro es una struct timeval. Si una función de entrada o salida bloquea durante este período de tiempo, y los datos han sido enviados o recibidos, el valor de retorno de esa función será la cantidad de datos transferidos; si no hay datos ha sido transferido y el tiempo de espera ha sido alcanzado entonces se devuelve -1 con errno conjunto EAGAIN o EWOULDBLOCK tan si el socket se especificó para ser sin bloqueo. Si el tiempo de espera se establece en cero (valor predeterminado), la operación nunca expirará.
Su hilo principal puede empujar cada descriptor de archivo en un queue
usando decir un mutex impulso para el acceso a la cola, a continuación, iniciar 1 - N hilos para hacer el envío real mediante el bloqueo de E/S con mando tiempos de espera.
Su función de envío debe ser algo como esto (suponiendo que se está configurando un tiempo de espera):
// blocking send, timeout is handled by caller reading errno on short send
int doSend(int s, const void *buf, size_t dataLen) {
int totalSent=0;
while(totalSent != dataLen)
{
int bytesSent
= send(s,((char *)data)+totalSent, dataLen-totalSent, MSG_NOSIGNAL);
if(bytesSent < 0 && errno != EINTR)
break;
totalSent += bytesSent;
}
return totalSent;
}
La bandera MSG_NOSIGNAL
asegura que su aplicación no es matado por escrito a una toma de corriente que se ha cerrado o se restablece por el par. A veces, las operaciones de E/S se ven interrumpidas por señales, y la comprobación de EINTR
le permite reiniciar el send
.
En general, debe llamar al doSend
en un bucle con trozos de datos que son de tamaño TCP_MAXSEG
.
En el lado de recepción puede escribir una función de bloqueo de recv similar utilizando un tiempo de espera en una secuencia separada.
Más información? ¿Se está transfiriendo el archivo con éxito, solo a un ritmo más lento o la transferencia está fallando? Si está fallando, ¿dónde está fallando? ¿Hay algo que se está transmitiendo o está fallando a la mitad? –
@Robert, gracias. La transferencia falla. Si transfiero una carpeta contiene, por ejemplo, 2 GB de archivos de 3 KB a 50 KB, a veces transfiere ~ 0.5 GB, a veces ~ 1.3 GB de datos y luego falla. – rkellerm
¿Qué mensajes de error está recibiendo y qué lado está cerrando la conexión? ¿Está utilizando E/S bloqueante o no bloqueante? ¿Tienes un hilo dedicado haciendo E/S? Cuantos más detalles, mejor, y si podría publicar fragmentos de código que serían los mejores. –