2010-02-27 30 views
7

Bir C/C++ istemci/sunucu soketi uygulaması programlıyorum. Bu noktada, istemci kendisini her 50 ms'de bir sunucuya bağlar ve bir mesaj gönderir.C yuva istemci/sunucu gecikmesi

birisini Has ... Aniden, sunucu şey daha ve bir kerede daha sonra 5 mesajlar ... Ve bazen her şey çalışıyor aldığında değildir:

Herşey eserleri gibi görünüyor, ama veri akışı sürekli değildir Bu garip davranışın kökeni hakkında bir fikir?

kod kısmı:

Müşteri:

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

Sunucu:

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

Düzenlemeler: Denedim 1. yapmak

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

Hem istemcide hem de sunucuda, ancak sorun hala var.

2.Yes bu bağlantıların/deconnections çok inneficient, ama ben çalıştığınızda Nihayet

... Sonra mesajı sadece bir kez gönderilir

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

yazma (veya gelen) için:

TCP_NODELAY'i sunucu tarafındaki istemci soketine takmayı unutmuştum. Şimdi mükemmel çalışıyor! İşlemleri iş parçacığı içerisine sokup soketlerin açık kalmasını sağlarım. Teşekkür ederiz tüm :)

cevap

10

"Nagle delay" adı verilen budur. Bu algoritma, bazı zaman aşımının sona ermesine kadar ağa herhangi bir şey göndermeden önce daha fazla veri gelmesi için TCP yığında bekliyor. Bu nedenle Nagle zaman aşımını (http://fourier.su/index.php?topic=249.0) değiştirmeli veya Nagle gecikmesini (http://www.unixguide.net/network/socketfaq/2.16.shtml) devre dışı bırakmalısınız, böylece send numaralı çağrı için veri gönderilecektir.

+0

Burada insanların bilgisi her zaman hayranlık duyuyorum. Çok teşekkür ederim. Bunu bir süre içinde deneyeceğim :) – Klaus

+0

+1 İlgili kavrama işaret etmek için. –

+0

Yukarıdaki cevabımı görün. – Klaus

3

Veri göndermeyi hemen zorlamak için TCP_NODELAY soket seçeneğini kullanabilirsiniz.

5

Zaten yanıtlarınızda gördüğünüz gecikmeler,soket seçeneği ayarlanarak devre dışı bırakılabilen TCP dahili Nagle algorithm nedeniyle gerçekleşmiştir.

Sabit bağlantı ve bağlantıların kesilmesi nedeniyle soket iletişiminizin çok verimsiz olduğu gerçeğine işaret etmek isterim. İstemcinin sunucuya her bağlandığında, three way handshake gerçekleşir ve bağlantı koparmak için dört paketin tamamlanması gerekir. Temel olarak TCP'nin faydalarının çoğunu kaybedersiniz ama tüm dezavantajlarına maruz kalırsınız.

O olurdu çok her istemci sunucuya kalıcı bağlantıyı sürdürmek için daha verimli. select(2), veya daha iyisi, Linux'ta epoll(4) veya FreeBSD ve Mac'te kqueue(2), çoklu soketlerde IO kullanımı için çok uygun çerçevelerdir.

+1

Sadece el sıkışma ve gözyaşları değil, her zaman yeni bir bağlantı oluşturduğunuzda yavaş başlangıçtan geçebilirsiniz * tekrar *. – ephemient

+0

Evet, o da. Teşekkürler. –

+0

Yukarıdaki cevabımı görün. – Klaus