2010-02-27 15 views
7

Estoy programando una aplicación de sockets cliente/servidor C/C++. En este punto, el cliente se conecta al servidor cada 50 ms y envía un mensaje.sockets C cliente/servidor retraso

Todo parece a las obras, pero el flujo de datos no es continua: De repente, el servidor no recibe nada más, y luego 5 mensajes a la vez ... Y a veces todo funciona ...

tiene a alguien una idea del origen de este extraño comportamiento?

Alguna parte del código:

Cliente:

while (true) 
{ 
if (SDL_GetTicks()-time>=50) 
{ 
socket = new socket(); 
socket->write("blah"); 
message.clear(); 
message = socket->read(); 
socket->close(); 
delete socket; 
time=SDL_GetTicks(); 
} 
} 

Servidor:

while (true) { 
fd_set readfs; 
struct timeval timeout={0,0}; 
FD_ZERO(&readfs); 
FD_SET(sock, &readfs); 
select(sock + 1, &readfs, NULL, NULL, &timeout) 
if(FD_ISSET(sock, &readfs)) 
{ 
SOCKADDR_IN csin; 
socklen_t crecsize = sizeof csin; 
SOCKET csock = accept(sock, (SOCKADDR *) &csin, &crecsize); 
sock_err = send(csock, buffer, 32, 0); 
closesocket(csock); 
} 
} 

ediciones: 1. Se ha intentado realizar

int flag = 1; 
setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof flag); 

Tanto en el cliente como en el servidor, pero el problema sigue ahí.

2.Yes esas conexiones/deconnections son muy inneficient, pero cuando trato de escribir

socket = new socket(); 
while (true) 
{ 
if (SDL_GetTicks()-time>=50) 
{ 
socket->write("blah"); 
message.clear(); 
message = socket->read(); 
time=SDL_GetTicks(); 
} 
} 

A continuación, el mensaje sólo se envía una vez (o recibidas) ...

Por último:

Había olvidado aplicar TCP_NODELAY al socket del cliente en el lado del servidor. ¡Ahora funciona perfectamente! Pongo los procesos en hilos para que los enchufes se mantengan abiertos. Gracias a todos :)

Respuesta

10

Esto es lo que se llama "Nagle delay". Este algoritmo está esperando en la pila TCP para que lleguen más datos antes de enviar algo a la red hasta que caduque el tiempo de espera. Por lo tanto, debe modificar el tiempo de espera de Nagle (http://fourier.su/index.php?topic=249.0) o desactivar el retardo de Nagle (http://www.unixguide.net/network/socketfaq/2.16.shtml), de modo que los datos se enviarán por llamada a send.

+0

Siempre estoy fascinado por el conocimiento de las personas aquí. Muchas gracias. Lo intentaré en un momento :) – Klaus

+0

+1 para señalar el concepto involucrado. –

+0

Ver mi respuesta arriba. – Klaus

3

Puede usar la opción de socket TCP_NODELAY para forzar el envío de datos inmediatamente.

5

Como otros ya respondieron, las demoras que ve son debidas al TCP incorporado Nagle algorithm, que se puede desactivar configurando la opción de socket TCP_NODELAY.

Me gustaría señalarle el hecho de que las comunicaciones de su zócalo son muy ineficientes debido a las constantes conexiones y desconexiones. Cada vez que el cliente se conecta al servidor, se produce el three way handshake, y el corte de la conexión requiere cuatro paquetes para completarse. Básicamente, usted pierde la mayoría de los beneficios de TCP pero incurre en todos sus inconvenientes.

Sería mucho más eficiente para que cada cliente mantenga una conexión constante con el servidor. select(2), o mejor aún, epoll(4) en Linux, o kqueue(2) en FreeBSD y Mac, son marcos muy convenientes para manejar IO en múltiples sockets.

+1

No solo el protocolo de enlace y las desconexiones, sino que cada vez que se establece una nueva conexión, se puede iniciar de nuevo *. – ephemient

+0

Sí, eso también. Gracias. –

+0

Ver mi respuesta arriba. – Klaus