响应标头和非HTTP数据的HTTP分离

时间:2012-02-09 14:27:30

标签: c++ http boost http-headers boost-asio

我只是在写一个小客户端HTTP应用程序。它只是向IP摄像机发送GET请求,然后以jpeg格式接收屏幕截图。

现在为了实现HTTP我正在使用Boost Asio。因此,对于第一次尝试,我几乎都在sync_client示例Boost Asio Sync HTTP Client Example

现在主要是我对标题和数据的分离感到有点担心。

首先我得到回复的第一行:

boost::asio::streambuf response;
boost::asio::read_until(*m_Socket, response, "\r\n");

std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;

 if (!response_stream || http_version.substr(0, 5) != "HTTP/")
 {
     std::cout << "Invalid response\n";
     return;
 }

uint32_t status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);  

 if (status_code != 200)    // 200 = status code OK
 {
     std::cout << "Response returned with status code " << status_code << "\n";
     return;
 }

现在直到这里一切都很清楚。我正在阅读第一个新行,然后检查缓冲区中的内容。

现在我正在尝试阅读标题的第二部分:

 boost::asio::read_until(*m_Socket, response, "\r\n\r\n");

 std::string header;
 while (std::getline(response_stream, header) && (header != "\r"))
 {
      std::cout << header << "\n";
 }
 std::cout << "\n";

现在我有一些问题:

  1. while循环正在搜索,直到有一个空行(\r唯一独立的行)。现在,如果我假设\r定义了新行,为什么我在\r\n\r\n使用boost::asio::read_until?我的意思是我会期待一个或另一个,但两者都是?

  2. 如果我使用boost::asio::read_until作为分隔符调用\r\r方法,则会抛出End of File异常。这与我的while循环搜索相反,因为它正在寻找\r\r(因为它看起来是一行一行,每行都以\r结束)

  3. 所以你可以看到我非常担心如何在我的标题内划分东西。它越来越甚至沃瑟因为boost::asio::read_until调用并总是比delmiter进一步阅读(其实这是正常的,因为它在文档中真实提到),但仍有点始终具有相同的数据跟踪(从actualy JPEG) ,跟随长度相同。

    也许有人可以启发我?

2 个答案:

答案 0 :(得分:3)

'\ r'是回车符(CR)字符,'\ n'是换行符(LF)字符。 HTTP消息行以“\ r \ n”(CRLF)终止。

来自“HTTP The Definitive Guide”:

  

值得指出的是,虽然是HTTP规范   终止线是CRLF,强大的应用也应该接受   换行符。一些较旧或损坏的HTTP应用程序不会   总是发送回车和换行。

似乎让你失望的是,某些行I / O函数(在本例中为std :: getline())会自动删除尾部'\ n',因此您只能看到前面的'\ r'。我认为你应该做的是寻找一个空行(而不是只有'\ r'的行)。并且只有'\ r'的行应该被视为空行。

答案 1 :(得分:2)

"\r\n\r\n"分隔符用于将标题与实际服务器的响应(您正在获取的JPEG图像)分开。这就是你使用它的原因;标题由"\r\n"分隔。

您应该阅读"\r\n\r\n"。之后发生的一切都是JPEG图像。请注意,您可以通过检查Content-Length标头来猜测文件的长度,或者直到服务器关闭套接字才能读取。