C++ recv()存在延迟问题
我注意到,这个问题已经被问了很多次,但似乎没有一个解决方案适用于我。在继续之前,我将为您发布一些代码:C++ recv()存在延迟问题,c++,sockets,recv,C++,Sockets,Recv,我注意到,这个问题已经被问了很多次,但似乎没有一个解决方案适用于我。在继续之前,我将为您发布一些代码: // Await the response and stream it to the buffer, with a physical limit of 1024 ASCII characters stringstream input; char buffer[4096*2]; while (recv(sock, buffer, sizeof(buffer
// Await the response and stream it to the buffer, with a physical limit of 1024 ASCII characters
stringstream input;
char buffer[4096*2];
while (recv(sock, buffer, sizeof(buffer) - 1, MSG_WAITALL) > 0)
input << buffer;
input << '\0';
// Close the TCP connection
close(sock);
freehostent(hostInfo);
//等待响应并将其流式传输到缓冲区,物理限制为1024个ASCII字符
串流输入;
字符缓冲区[4096*2];
而(recv(sock,buffer,sizeof(buffer)-1,MSG_WAITALL)>0)
输入接收需要很长时间的原因是,您告诉系统等待,直到它接收到您要求的所有数据,即8k字节,或者连接出错或关闭。这就是标志MSG_WAITALL
的作用
解决这个问题的一个方法是使套接字非阻塞,并在循环中进行连续读取,直到出现错误或连接关闭
如何使套接字无阻塞取决于平台、Windows上使用函数完成的操作、Linux或类似系统上使用函数完成的操作:
int flags = fcntl(sock, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(sock, F_SETFL, flags);
然后从套接字中读取如下内容:
std::istringstream input;
for (;;)
{
char buffer[256];
ssize_t recvsize;
recvsize = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (recvsize == -1)
{
if (errno != EAGAIN && errno != EWOULDBLOCK)
break; // An error
else
continue; // No more data at the moment
}
else if (recvsize == 0)
break; // Connection closed
// Terminate buffer
buffer[recvsize] = '\0';
// Append to input
input << buffer;
}
int rc;
while ((rc = recv(sock, buffer, sizeof(buffer) - 1, MSG_WAITALL)) > 0)
{
buffer[rc] = '\0';
input << buffer;
}
这里出现的问题是因为您正在指定MSG_WAITALL
标志。它强制recv
保持阻塞状态,直到接收到所有指定的字节(在您的情况下是sizeof(buffer)-1
,而另一方发送的消息明显较小),或者发生错误,并返回-1,同时适当设置errno
变量
我认为,更可取的选择是使recv
在循环中没有任何标志,直到另一端的套接字关闭(recv返回0)或接收到某个分隔符
然而,使用input时应该小心。您应该注意到缓冲区中读取了多少字节,并且只将那个么多字节写入输入。无法保证数据将包含或不包含空终止符。根据您的请求判断,您正在与web服务器通信。您的请求中的一个问题是换行符。HTTP标准规定应该使用“\r\n”
作为换行符,而不是单个“\n”
。
int rc;
while ((rc = recv(sock, buffer, sizeof(buffer) - 1, MSG_WAITALL)) > 0)
{
buffer[rc] = '\0';
input << buffer;
}