问题描述
我很难弄清TCP客户端服务器应用程序中的错误。我面临的问题:在我的recv函数的do-while循环中,如果条件为bytes > 0
,该函数将永远挂起。用bytes == NMAX
代替,一切正常,除非NMAX等于1。一些注意事项:进行一次send-recv可以正常工作,但是尝试先进行send-recv然后recv-send会永远挂起。 NMAX
是默认设置为4096
的常量。首先运行服务器,然后运行客户端。
这是我的发送功能:
ssize_t sendData(const std::string data,int fd)
{
ssize_t total = data.length(),bytes,sent = 0;
do
{
ssize_t chunk = total > NMAX ? NMAX : total;
bytes = send(fd,data.c_str() + sent,chunk,0);
if (bytes == -1)
{
throw std::system_error(errno,std::generic_category(),"Error sending data");
}
total -= bytes;
sent += bytes;
} while (total > 0);
return sent;
}
这是我的recv函数:
std::string recvData(int fd)
{
ssize_t bytes;
std::string buffer;
do
{
std::vector<char> data(NMAX,0);
bytes = recv(fd,&data[0],NMAX,"Error receiving data");
}
buffer.append(data.cbegin(),data.cend());
} while (bytes > 0); // Replacing with bytes == NMAX partially fixes the issue,why?
return buffer;
}
这是客户端的主要功能:
std::cout << "Sent " << sendData(data) << " bytes\n";
std::cout << "Received: " << recvData() << "\n";
这是服务器的主要功能:
std::cout << "Received: " << recvData(client) << "\n";
std::cout << "Sent " << sendData("Hello from the server side!",client) << " bytes\n";
解决方法
程序的问题是接收方不知道总共要接收多少个字节。因此,它将无休止地尝试读取更多字节。
它“挂起”的原因是您执行了阻塞的系统调用(recv
),只有在收到至少1个字节以上时,该系统调用才会取消阻塞。但是,由于对等方不会发送更多数据,因此永远不会发生。
要解决此问题,您需要对数据采用适当的线格式,以指示所传输数据的大小或开始和结束的位置。常用的方法是以二进制形式为其长度加上前缀(例如32位无符号int,采用大字节序格式)。另一种方法是在数据中包含指示其结束的指示符(例如,HTTP中的\r\n\r\n
换行符)。
顺便说一句:您的send
函数在data.length() == 0
的情况下并不理想。在这种情况下,您将以0个字节执行send
系统调用-这是不必要的。