Winsock отправляет дополнительные данные - PullRequest
1 голос
/ 26 января 2012

Я пишу небольшое клиент-серверное приложение на c ++ с winsock, и я не могу объяснить несколько вещей, которые происходят .. Я написал 2 основные функции, которые отправляют / получают все данные через TCP-соединение ..

bool sending(SOCKET source, char* buff, int size, int flags = 0)
{
    int sent = 0;
    int totalst = 0;
    int total = size;
    while(totalst != total)
    {
        sent = send(source, buff+totalst, size-totalst, flags);
        if(sent > 0)
        {
            totalst += sent;
        }
        if(sent == SOCKET_ERROR)
        {
            return false;
        }       
    }   
    return true;
}

bool receive(SOCKET source, char* buff, int size, int flags = 0)
{
    int rec = 0;
    int totalrc = 0;
    int total = size;
    while(totalrc != total)
    {
        rec = recv(source, buff+totalrc, size-totalrc, flags);
        if(rec > 0)
        {
            totalrc += rec;
        }
        if(rec == SOCKET_ERROR)
        {
            return false;
        }
    }
    return true;
}

Сервер отправляет целое число, которое содержит размер блока данных, который будет следовать за ним. Этот размер блока данных в моем случае не должен изменяться, он всегда должен быть 92600 байт, ноиногда клиент получает 92604 байта вместо этого.Странно то, что если я заставляю сервер ждать после отправки размера bock и самого блока (с Sleep), он всегда отправляет то, что я ожидал ..

int i=0;                    
while(i < 100)
{
    i++;
    dat = getData();                                
    len = sizeof(dat);
    sending(source, (char*)&len, sizeof(len));
    sending(source, dat, len);
    Sleep(200);    
}

Может ли быть так, что клиент получаетневерное значение байтов из-за задержки?Есть ли способ исправить это?Любая помощь приветствуется!

Ответы [ 2 ]

2 голосов
/ 26 января 2012

Рассмотрим этот пример:

char *x = "!";
send(socket, x, 1); // destination, buffer, size
send(socket, x, 1);
send(socket, x, 1);
send(socket, x, 1);

Что вы ожидаете здесь?

char buffer[4];
recv(socket, buffer, 4); // source, buffer, size

На практике данные, отправленные четырьмя send, могут быть получены водин recv.У вас нет никаких гарантий, что если вы сделаете n звонки на send, вы совершите n звонки на recv для получения всех данных.

Как прокомментировал nos, TCP не 'реализовать границы сообщений.Это ваша работа на прикладном уровне.Winsock не отправляет дополнительные данные, вы делаете.

0 голосов
/ 26 января 2012

У вас есть ошибка как в отправляющей, так и в принимающей функции.

Вы правильно отслеживаете общее количество отправленных / полученных байтов, чтобы правильно выйти из цикла, но забыли отрегулировать значение "buff""и" размер "в последующих вызовах для отправки / recv.Если буфер для отправки должен быть передан с несколькими вызовами для отправки, вы отправите неверные данные.

Аналогичным образом, если необходимо несколько вызовов «recv», вы перезапишете данные, скопированные в начале буфера.

Должно читаться:

sent = send(source, buff+totalst, size-totalst, 0);

Аналогично для случая recv:

rec = recv(source, buff + totalrc, size-totalrc, 0);

Я не уверен, что это вызывает вашу проблему, но у меня естьесли вы чувствуете, что сценарий, указанный в todda, верен, то эта ошибка искажает ваши потоки данных.

Имеет смысл?Кроме того, вы должны быть готовы обработать случай, когда recv () вернет 0.

Надеюсь, это поможет.

...