CのウィンドウでTCP通信をシミュレートしています。送信者と受信者が通信しています。
送信者は特定のサイズのパケットを受信者に送信します。受信者はそれらを取得し、受信した各パケットの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()
、2バイトを取得し、while条件を続行します。これにより、ループが再度繰り返され、送信者が送信するものがないためにブロックtotalChunkLen < packetSize
されているため、がスタックします。 。2<4
recv()
送信側では、ACKが返されなかったために接続を閉じることができないため、一種のデッドロックになります。受信者はさらにパッケージを待機しているためスタックしていますが、送信者は送信するものがありません。
recv()
タイムアウトを使用したり、パッケージヘッダーに特殊文字を挿入して、それが最後の文字であることをマークしたりしたくありません。
私に何ができる?