【发布时间】:2011-07-09 20:22:00
【问题描述】:
我正在用 C 语言模拟 Windows 上的 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() 得到两个字节,继续到while 条件,然后totalChunkLen < packetSize 因为2<4 所以它再次迭代循环并且卡在recv() 因为它被阻塞了,因为发送者没有什么可以发送。
在发送方我无法关闭连接,因为我没有收到 ACK,所以这是一种死锁。接收方卡住了,因为它正在等待更多的包裹,但发送方没有要发送的东西。
我不想对recv() 使用超时,也不想在包头中插入一个特殊字符来标记它是最后一个。
我能做什么?
【问题讨论】:
标签: c++ windows sockets send recv