2012-02-09 50 views
1

我只是写了一个小小的客户端HTTP应用程序。它只是发送一个GET请求到IP摄像头,然后以jpeg格式接收截图。响应头和非HTTP数据的HTTP分离

现在为了实现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; 
} 

即日起至这里的一切很清楚,me.I'm读书,直到第一个新行,然后检查东西在我的缓冲区。

现在,我尝试读取头的第二部分:

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\nboost::asio::read_until?我的意思是我会期望这两者之一,但两者?

  2. 如果我用\r\r作为分隔符调用boost::asio::read_until方法,它会抛出End of File异常。这表示在相反的是,因为这是我while循环搜索是寻找一个\r\r(因为它看起来行之后的行,每行有\r关闭)

因此,大家可以看到林颇为担心如何在我的标题内划分内容。它变得更加糟糕,因为boost::asio::read_until调用总是读取比delmiter更远(这实际上是确定的,因为它在文档中提到过),但它仍然有相同的数据跟踪(来自实际的jpeg),具有相同的长度如下。

也许有人可以启发我吗?

+0

我强烈建议您使用[真正的,生产就绪的HTTP解析器](https://github.com/joyent/http-parser)。 – 2012-02-09 15:36:33

回答

3

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

从“HTTP权威指南”:

这是值得指出的是,虽然对 端接线路的HTTP规范CRLF,可靠的应用程序也应该接受只是一个 换行符。一些旧的或破碎的HTTP应用程序不总是发送回车符和换行符。

什么似乎是抛弃你的是一些行I/O函数(在这种情况下std :: getline())自动剥离尾随'\ n',所以你只看到前面的'\ r ”。我认为你应该做的是寻找一条空白的行(而不是只有'\ r'的行)。只有'\ r'的行应该被认为是空行。

+0

啊,是的,现在我明白了......我没有想到std :: getline()可能会切割一些东西。所以,如果(如你所说)getline去掉“\ n”,这样做更有意义!谢谢!!! – Toby 2012-02-09 15:20:34

2

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

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