C sockets задержка клиента / сервера

я программирую приложение сокетов клиента / сервера C / C++. На этом этапе клиент подключается к серверу каждые 50 мс и отправляет сообщение.

кажется, что все работает, но поток данных не является непрерывным: внезапно сервер больше ничего не получает, а затем 5 сообщений сразу... И иногда все работает...

есть ли у кого-нибудь идея о происхождении этого странного поведения ?

часть код:

клиент:

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

сервер:

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

изменения: 1. Я пытался сделать

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

как в клиенте, так и на сервере, но проблема все еще существует.

2.Да этих соединений/deconnections очень inneficient, но когда я пытаюсь написать

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

затем сообщение отправляется только один раз (или получил)...

и наконец:

Я забыл примените TCP_NODELAY к клиентскому сокету на стороне сервера. Теперь он работает отлично ! Я помещаю процессы в потоки, чтобы сокеты оставались открытыми. Спасибо всем :)

3 ответов


Это то, что называется "Нэгл задержки". Этот алгоритм ожидает в стеке TCP больше данных, прежде чем отправлять что-либо в сеть, пока не истечет некоторый тайм-аут. Так что вы должны изменить Нэгл ожидания (http://fourier.su/index.php?topic=249.0) или отключить Нэгл задержку (http://www.unixguide.net/network/socketfaq/2.16.shtml), поэтому данные будут отправлены в send звонок.


как уже ответили другие задержки, которые вы видите, из-за встроенного TCP алгоритм Nagle, который можно отключить, установив гнездо.

Я хотел бы указать вам на тот факт, что ваши сокеты связи очень неэффективны из-за постоянных подключений и отключений. Каждый раз, когда клиент подключается к серверу, есть трехстороннее рукопожатие это происходит,и разрыв соединения требует четырех пакетов для завершения. В основном вы теряете большинство преимуществ TCP, но несете все его недостатки.

было бы много более эффективно для каждого клиента поддерживать постоянное соединение с сервером. select(2) или еще лучше epoll(4) в Linux или kqueue(2) на FreeBSD и Mac, очень удобные рамки для обработки ввода-вывода на нескольких сокетах.


вы можете использовать опцию сокета TCP_NODELAY для принудительной отправки данных немедленно.