【问题标题】:Receive recv data until end of stream (using HTTP)?接收recv数据直到流结束(使用HTTP)?
【发布时间】:2015-12-27 15:43:48
【问题描述】:

我是第一次尝试 C++ 套接字,我遇到了第一个障碍。我已经使用send 函数(GET / HTTP/1.1\r\n\r\n)向谷歌发送了一些数据,现在我正在尝试接收响应。我当前的代码:

char buffer[256];
std::string result = "";

int resultSize = 0;
bool receive = true;
while (receive) {
    resultSize = recv(dataSocket, buffer, sizeof(buffer) - 1, 0);
    buffer[resultSize] = '\0'; // Add NULL terminating character to complete string
    result += buffer;

    for (int i = 0; i < resultSize; i++) {
        if (buffer[i] == '\0') {
            receive = false;
        }
    }
}

return result;

使用大小为 256 的缓冲区来演示问题,即如果页面包含的字节数多于我在缓冲区中接收的字节数,那么它在第一次尝试时不会接收到所有内容。我尝试循环直到数据包含空终止符 ('\0'),这似乎不起作用。我还尝试检查空行 ('\r\n'),但效果不佳,因为页眉和页面的 HTML 内容之间有一个空行。

我注意到我可以使用 Content-Length 标头来解决这个问题。但是,我不确定如何获取该标头,因为它至少需要一个 recv 调用,并且是否有一种好的、安全和有效的方法来做到这一点。我也不确定当响应不包含 Content-Length 标头时该怎么办,因为程序将陷入无限循环。

所以如果有一种方法可以让我重复 recv 直到到达 HTTP 流的末尾,我想知道它。

如果有人能帮我解决这个问题,我将不胜感激!

【问题讨论】:

  • “第一次尝试时没有收到所有内容”。为什么要呢?它在哪里说呢?如果愿意,TCP 可以一次为您提供一个字节。注意,您不是在此处检查错误或流结束。而且 HTTP 1.1 响应的结尾不是由流的结尾定义的:可能有一个 Content-length 标头或多部分,每个部分都有自己的长度。请参阅 RFC 2616。
  • 您应该循环直到recv 返回 0。(或 -1,表示发生错误。或 SOCKET_ERROR,如果在 Windows 上)
  • @immibis:正确的行为是当HTTP响应数据告诉你停止阅读时停止阅读。首先读取响应标头(一直读取直到到达\r\n\r\n),然后解析标头,然后按照标头的指示读取响应正文的其余部分,并且仅在到达响应的末尾时才停止读取标头,或服务器关闭连接时,以先遇到者为准。
  • @EJP 冷静下来,我从没想过会这样。整个问题是关于如何检测流的结尾。
  • @Qub1:阅读RFC 2616 Section 4 HTTP Message,尤其是Section 4.2 Message HeadersSection 4.4 Message Length。 4.4 准确地告诉您要查找哪些标头以及如何处理它们。不,正则表达式还不够好,因为标题不区分大小写,可以按任何顺序排列,在它们及其值周围有额外的空格,等等。你需要一个真正的解析器。

标签: c++ sockets http recv


【解决方案1】:

正确的行为是当HTTP响应数据告诉你停止阅读时停止阅读。首先读取响应标头(一直读取直到到达\r\n\r\n),然后解析标头,然后按照标头的指示读取响应正文的其余部分,并且仅在到达响应的末尾时才停止读取标头,或服务器关闭连接时,以先遇到者为准。 ——雷米·勒博

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-23
    • 2014-01-14
    • 2020-08-29
    • 1970-01-01
    • 2019-01-25
    • 2011-05-29
    • 2020-06-09
    • 1970-01-01
    相关资源
    最近更新 更多