В основе транспортного стека 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.
Так как мне получить последние данные?