C сокеты клиент / сервер лаг - PullRequest
7 голосов
/ 27 февраля 2010

Я программирую приложение клиент / серверные сокеты на 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. Да, эти соединения / разъединения очень неэффективны, но когда я пытаюсь написать

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

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

Наконец:

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

Ответы [ 3 ]

9 голосов
/ 27 февраля 2010

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

5 голосов
/ 27 февраля 2010

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

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

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

3 голосов
/ 27 февраля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...