2010-02-27 34 views
7

Tôi đang lập trình ứng dụng ổ cắm máy khách/máy chủ C/C++. Tại thời điểm này, máy khách kết nối chính nó với máy chủ mỗi 50ms và gửi một thông báo.C ổ cắm máy khách/máy chủ lag

Tất cả mọi thứ dường như tác phẩm, nhưng dòng chảy dữ liệu không liên tục: Đột nhiên, máy chủ không nhận được bất cứ điều gì nhiều hơn, và sau đó 5 tin nhắn cùng một lúc ... Và đôi khi mọi thứ hoạt động ...

Có ai đó một ý tưởng về nguồn gốc của hành vi kỳ lạ này?

Một số phần của mã:

Chủ đầu tư:

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

Chỉnh sửa: 1. Tôi đã cố gắng để làm

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

Trong cả máy khách và máy chủ, nhưng vấn đề vẫn còn đó.

2.Yes những kết nối/deconnections rất inneficient, nhưng khi tôi cố gắng viết

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

Sau đó, thông điệp chỉ được gửi một lần (hoặc nhận) ...

Cuối cùng:

Tôi đã quên áp dụng TCP_NODELAY cho ổ cắm máy khách ở phía máy chủ. Bây giờ nó hoạt động hoàn hảo! Tôi đặt các quy trình trong các chủ đề sao cho các ổ cắm luôn mở. Cảm ơn tất cả các bạn :)

Trả lời

10

Đây được gọi là "Nagle delay". Thuật toán này đang chờ đợi trên TCP stack cho nhiều dữ liệu hơn để đến trước khi thực sự gửi bất cứ điều gì đến mạng cho đến khi một số thời gian chờ hết hạn. Vì vậy, bạn nên sửa đổi thời gian chờ Nagle (http://fourier.su/index.php?topic=249.0) hoặc tắt trễ Nagle ở ​​tất cả (http://www.unixguide.net/network/socketfaq/2.16.shtml), do đó dữ liệu sẽ được gửi cho mỗi cuộc gọi send.

+0

Tôi luôn bị cuốn hút bởi kiến ​​thức của mọi người ở đây. Cảm ơn nhiều. Tôi sẽ cố gắng trong một thời gian :) – Klaus

+0

+1 để chỉ đến khái niệm liên quan. –

+0

Xem câu trả lời của tôi ở trên. – Klaus

3

Bạn có thể sử dụng tùy chọn socket TCP_NODELAY để buộc dữ liệu gửi ngay lập tức.

5

Như những người khác đã trả lời chậm trễ mà bạn nhìn thấy là do TCP built-in Nagle algorithm, có thể được vô hiệu hóa bằng cách thiết lập TCP_NODELAY tùy chọn socket.

Tôi muốn chỉ cho bạn thực tế là các liên lạc ổ cắm của bạn không hiệu quả do kết nối và ngắt kết nối liên tục. Mỗi khi khách hàng kết nối với máy chủ có three way handshake diễn ra, và kết nối tear-down yêu cầu bốn gói để hoàn thành. Về cơ bản bạn mất hầu hết các lợi ích của TCP nhưng phải chịu mọi nhược điểm của nó.

Nó sẽ là nhiều hiệu quả hơn cho từng khách hàng để duy trì kết nối liên tục với máy chủ. select(2) hoặc thậm chí tốt hơn, epoll(4) trên Linux hoặc kqueue(2) trên FreeBSD và Mac, là các khung rất thuận tiện để xử lý IO trên nhiều ổ cắm.

+1

Không chỉ là bắt tay và teardowns, nhưng mỗi lần bạn tạo một kết nối mới, bạn sẽ phải trải qua quá trình khởi động chậm * một lần nữa *. – ephemient

+0

Vâng, cũng vậy. Cảm ơn. –

+0

Xem câu trả lời của tôi ở trên. – Klaus

Các vấn đề liên quan