2010-02-27 21 views
7

Sto programmando un'applicazione client/server socket C/C++. A questo punto, il client si connette al server ogni 50 ms e invia un messaggio.C socket socket client/server

tutto sembra opere, ma il flusso di dati non è continuo: Improvvisamente, il server non riceve nulla di più, e poi 5 messaggi in una volta ... E a volte tutto funziona ...

ha qualcuno un'idea dell'origine di questo strano comportamento?

Una parte del codice:

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(); 
} 
} 

Server:

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); 
} 
} 

Modifiche: 1. Ho cercato di fare

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

In entrambi i client e server, ma il problema è ancora lì.

2.Yes quelle connessioni/deconnections sono molto inneficient, ma quando provo a scrivere

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

Quindi il messaggio viene inviato solo una volta (o ricevuti) ...

Infine:

Avevo dimenticato di applicare TCP_NODELAY al socket client sul lato server. Ora funziona perfettamente! Metto i processi nelle discussioni in modo che le prese si tengano aperte. Grazie a tutti :)

risposta

10

Questo è ciò che viene chiamato "Nagle delay". Questo algoritmo è in attesa sullo stack TCP per l'arrivo di più dati prima di inviare effettivamente qualsiasi cosa alla rete fino a che non scade un certo timeout. Quindi è necessario modificare il timeout Nagle (http://fourier.su/index.php?topic=249.0) o disabilitare il ritardo Nagle (http://www.unixguide.net/network/socketfaq/2.16.shtml), quindi i dati verranno inviati per chiamata send.

+0

Sono sempre affascinato dalla conoscenza delle persone qui. Grazie mille. Lo proverò tra poco :) – Klaus

+0

+1 per indicare il concetto in questione. –

+0

Vedere la mia risposta sopra. – Klaus

3

È possibile utilizzare l'opzione di socket TCP_NODELAY per forzare l'invio dei dati immediatamente.

5

Come altri già hanno risposto i ritardi sono dovuti al TCP integrato Nagle algorithm, che può essere disabilitato impostando l'opzione socket TCP_NODELAY.

Vorrei evidenziare il fatto che le comunicazioni del socket sono molto inefficienti a causa di connessioni e disconnessioni costanti. Ogni volta che il client si connette al server, viene eseguito il numero three way handshake e il download delle connessioni richiede il completamento di quattro pacchetti. Fondamentalmente si perde la maggior parte dei benefici del TCP, ma si incorre in tutti i suoi inconvenienti.

Sarebbe molto più efficiente per ogni client per mantenere la connessione permanente al server. select(2), o anche meglio, epoll(4) su Linux, o kqueue(2) su FreeBSD e Mac, sono framework molto convenienti per la gestione di IO su più socket.

+1

Non solo l'handshake e il teardown, ma ogni volta che si crea una nuova connessione si passa di nuovo in slow-start * di nuovo *. – ephemient

+0

Sì, anche quello. Grazie. –

+0

Vedere la mia risposta sopra. – Klaus