2012-02-09 2 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. в то время как цикл поиска до тех пор, пока не будет пустым line (единственная линия, где \r стоит само собой). Теперь, если я предполагаю, что новая строка определена \r, почему я использую \r\n\r\n по адресу boost::asio::read_until? Я имею в виду, я бы ожидал, что тот или другой, но оба?

  2. Если я вызываю метод boost::asio::read_until с \r\r в качестве разделителя, он выдает исключение End of File. Это стоит в отличие от того, что моя в то время как цикл поиска, поскольку это ищет \r\r (так как она выглядит линия после линии, и каждая линия закрывается с \r)

Так как вы можете видеть Im весьма беспокоит, как чтобы разделить материал внутри моего заголовка. Это становится еще хуже, потому что вызов boost::asio::read_until всегда читается дальше, чем delmiter (на самом деле это нормально, поскольку он упоминается в документации), но все же у него всегда есть один и тот же след данных (из фактического jpeg), с тем же длина последующий.

Может быть, кто-нибудь может просветить меня?

+0

Я настоятельно рекомендую вам использовать [настоящий, готовый к производству HTTP-парсер] (https://github.com/joyent/http-parser). –

ответ

3

'\ r' - символ возврата каретки (CR), а '\ n' - символ линии (LF). Строки HTTP-сообщений завершаются символом «\ r \ n» (CRLF).

С «HTTP The Definitive Guide»:

Стоит отметить, что в то время как спецификация HTTP для заканчивающихся линий CRLF, надежные приложения также должны принимать только символ перевода строки. Некоторые старые или взломанные HTTP-приложения не всегда отправляют как возврат каретки, так и линию.

Что, кажется, бросает тебя в том, что некоторые линии функции ввода/вывода (в данном случае станд :: GetLine()) автоматически обнажать завершающую «\ п», так что вы видите только предшествующее «\ г ». Я думаю, что вы должны делать, ищет пустую строку (а не строку с только «\ r»). И строка, которая только «\ r», должна считаться пустой строкой.

+0

Ahhh да, теперь я понял ... Я не думал о том, что std :: getline() может вырезать какой-то материал. Так что, если (как вы говорите), линия getline отключается от «\ n», это делает больше смысла !!! Спасибо!!! – Toby

2

Разделитель "\r\n\r\n" используется для разделения заголовков на фактический ответ сервера (который представляет собой изображение JPEG, которое вы извлекаете). Вот почему вы его используете; заголовки разделены "\r\n".

Вы должны прочитать до "\r\n\r\n". Все, что приходит после этого, - это изображение в формате JPEG. Обратите внимание, что вы можете угадать длину файла, проверив заголовок Content-Length или просто прочитав, пока сервер не закроет сокет.

Смежные вопросы