2010-02-27 14 views
7

Ich programmiere eine C/C++ - Client/Server-Sockets-Anwendung. An diesem Punkt verbindet sich der Client alle 50ms mit dem Server und sendet eine Nachricht.C Sockets Client/Server Verzögerung

Alles scheint funktioniert, aber der Datenfluss ist nicht kontinuierlich: Plötzlich wird der Server nichts mehr empfängt, und dann 5 Nachrichten auf einmal ... Und manchmal alles funktioniert ...

Hat jemand eine Vorstellung von der Herkunft dieses seltsamen Verhaltens?

Ein Teil des Codes:

Auftraggeber:

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

Edits: 1. Ich habe versucht,

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

In Client und Server, aber das Problem ist immer noch da.

2.Yes diese Verbindungen/deconnections sind sehr inneficient, aber wenn ich versuche

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

schreiben Dann wird die Nachricht nur einmal gesendet (oder empfangen) ...

Endlich:

Ich hatte vergessen, TCP_NODELAY auf den Client-Socket auf der Serverseite anzuwenden. Jetzt funktioniert es perfekt! Ich setze die Prozesse in Threads, damit die Sockets offen bleiben. Vielen Dank alle :)

Antwort

10

Dies ist, was "Nagle delay" genannt. Dieser Algorithmus wartet auf dem TCP-Stapel, bis weitere Daten ankommen, bevor tatsächlich etwas an das Netzwerk gesendet wird, bis ein Timeout abläuft. Daher sollten Sie das Nagle-Timeout (http://fourier.su/index.php?topic=249.0) ändern oder die Nagle-Verzögerung deaktivieren (http://www.unixguide.net/network/socketfaq/2.16.shtml), sodass Daten per send-Aufruf gesendet werden.

+0

Ich bin immer fasziniert von dem Wissen der Menschen hier. Vielen Dank. Ich werde das in einer Weile versuchen :) – Klaus

+0

+1 für auf das Konzept beteiligt zeigen. –

+0

Siehe meine Antwort oben. – Klaus

3

Sie können die TCP_NODELAY-Socket-Option verwenden, um das Senden der Daten sofort zu erzwingen.

5

Da andere bereits geantwortet haben, sind die angezeigten Verzögerungen auf TCP Nagle algorithm zurückzuführen, das durch Setzen der TCP_NODELAY Socket-Option deaktiviert werden kann.

Ich möchte Sie auf die Tatsache hinweisen, dass Ihre Socket-Kommunikation aufgrund konstanter Verbindungen und Verbindungen sehr ineffizient ist. Jedes Mal, wenn der Client eine Verbindung mit dem Server herstellt, gibt es die three way handshake, die ausgeführt wird, und ein Abbruch der Verbindung erfordert, dass vier Pakete abgeschlossen werden. Grundsätzlich verlieren Sie die meisten Vorteile von TCP, aber alle seine Nachteile.

Es wäre viel effizienter für jeden Client, dauerhafte Verbindung zum Server aufrechtzuerhalten. select(2), oder noch besser, epoll(4) auf Linux oder kqueue(2) auf FreeBSD und Mac, sind sehr praktische Frameworks für die Behandlung von IO auf mehreren Sockets.

+1

Nicht nur der Handshake und die Teardowns, sondern jedes Mal, wenn Sie eine neue Verbindung bilden, geht es durch den Slow-Start * wieder *. – ephemient

+0

Ja, das auch. Vielen Dank. –

+0

Siehe meine Antwort oben. – Klaus