Я имитирую связь TCP на окнах в C. У меня есть отправитель и получатель, связывающийся.
Отправитель отправляет пакеты определенного размера получателю.Получатель получает их и отправляет ACK для каждого полученного пакета обратно отправителю.Если отправитель не получил конкретный пакет (они пронумерованы в заголовке внутри пакета), он снова отправляет пакет получателю.Вот функция getPacket на стороне получателя:
//get the next packet from the socket. set the packetSize to -1
//if it's the first packet.
//return: total bytes read
// return: 0 if socket has shutdown on sender side, -1 error, else number of bytes received
int getPakcet(char* chunkBuff, int packetSize, SOCKET AcceptSocket)
{
int totalChunkLen = 0;
int bytesRecv = -1;
bool firstTime = false;
if(packetSize == -1)
{
packetSize = MAX_PACKET_LENGTH;
firstTime = true;
}
int needToGet = packetSize;
do
{
char* recvBuff;
recvBuff = (char*)calloc(needToGet, sizeof(char));
if(recvBuff == NULL)
{
fprintf(stderr, "Memory allocation problem\n");
return -1;
}
bytesRecv = recv(AcceptSocket, recvBuff, needToGet, 0);
if(bytesRecv == SOCKET_ERROR)
{
fprintf(stderr, "recv() error %ld.\n", WSAGetLastError());
totalChunkLen = -1;
return -1;
}
if(bytesRecv == 0)
{
fprintf(stderr, "recv(): socket has shutdown on sender side");
return 0;
}
else if(bytesRecv > 0)
{
memcpy(chunkBuff + totalChunkLen, recvBuff, bytesRecv);
totalChunkLen += bytesRecv;
}
needToGet -= bytesRecv;
}
while((totalChunkLen < packetSize) && (!firstTime));
return totalChunkLen;
}
Я использую firstTime
, потому что в первый раз получатель не знает нормальный размер пакета, который отправитель отправит ему, поэтомуЯ использую MAX_PACKET_LENGTH
, чтобы получить пакет, а затем установить нормальный размер пакета равным количеству полученных байтов.
Моя проблема - последний пакет.Это размер меньше, чем размер упаковки.Допустим, последний размер пакета равен 2, а нормальный размер пакета равен 4. Итак, recv()
получает два байта, переходит к условию while, затем totalChunkLen < packetSize
, потому что 2<4
, поэтому он повторяет цикл снова и застревает в recv()
потому что он блокирует, потому что отправителю нечего отправить.
Со стороны отправителя я не могу закрыть соединение, потому что я не получил ACK назад, так что это своего рода тупик.Получатель застрял, потому что он ожидает больше пакетов, но отправителю нечего отправить.
Я не хочу использовать тайм-аут для recv()
или вставить специальный символ в заголовок пакета, чтобы отметить, что онпоследний.
Что я могу сделать?