Почему происходит сбой recv, когда запрошенный размер буфера превышает объем доступных данных? - PullRequest
4 голосов
/ 14 января 2009

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

Я реализовал простой клиент для получения данных с сервера (написанный коллегой на Java). Протокол должен записывать длину данных (в сетевом порядке) в четыре байта, а затем данные. Сервер записывает данные в поток TCP в 1024-байтовых блоках. Клиент правильно получает длину буфера данных, выделяет память и многократно вызывает recv в цикле, чтобы получить все данные:

unsigned int TCP_BlockSize = 4096;
unsigned int len;
int result;

...code to request len...
unsigned char *buf = new unsigned char[len];

if( len > TCP_BlockSize)
{
Uint32 currentLen = 0;
result = 0;
Uint32 failCount = 0;
while( currentLen < len && result >= 0)
{
        result = recv( sock, buf + currentLen, TCP_BlockSize );
        if( result > 0 )
    {
        currentLen = currentLen + result;
    }
    else
        {
    break;
        }
}
}

Если я установлю TCP_BlockSize на 4095 или ниже, все будет хорошо, и я могу получать мультимегабайтные передачи. Когда я пытаюсь получить блоки размером 4096, последний запрос оставшихся данных, который len - currentLen

Еще одна деталь: сервер закрывает сокет после отправки последнего байта. Возникает вопрос: почему не будут возвращены оставшиеся данные? Похоже на дефект - не возвращать -1 из recv до тех пор, пока поток не станет пустым и закрыт, поскольку это неоднозначно, когда поток не пуст * и закрыт для получения -1 от RECV.

Так как мне получить последние данные?

1 Ответ

2 голосов
/ 14 января 2009

Попробуйте что-то вроде ...

to_rcv = (len - currentlen < TCP_BlockSize) ? len - currentlen : TCP_BlockSize;
result = recv( sock, buf + currentLen, to_rcv);

Таким образом, окончательное recv будет запрашивать только необходимую сумму, в противном случае будет запрашиваться TCP_BlockSize.

...