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;
}