2016-11-23 16 views
0

私はboost :: asioの基本例を使ってenpointに接続し、json応答を取得します。文字列が戻ったときにここでコードboost :: asio文字列としてstreambufレスポンスを取得しようとすると問題が発生する

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

// Check that response is OK. 
std::istream response_stream(&response); 
std::string http_version; 
response_stream >> http_version; 
unsigned int status_code; 
response_stream >> status_code; 
std::string status_message; 
std::getline(response_stream, status_message); 
if (!response_stream || http_version.substr(0, 5) != "HTTP/") { 
     LOG_ERROR << "invalid response"; 
     return -1; 
} 

resp_status_code_ = status_code; 

resp_status_code_ = status_code; 

if (status_code != 200) { 
     LOG_ERROR << "response did not returned 200 but " << status_code; 
     return -1; 
} 

//read until the response headers termination 
boost::asio::read_until(socket_, response, "\r\n\r\n"); 

//read the headers. 
std::string header; 
while (std::getline(response_stream, header) && header != "\r") { 
     ; 
} 

std::ostringstream ostringstream_content; 
if (response.size() > 0) 
     ostringstream_content << &response; 

boost::system::error_code error; 

boost::system::error_code error; 
while (true) { 
     size_t n = boost::asio::read(socket_, response, boost::asio::transfer_at_least(1), error); 

     if (!error) 
     { 
       if (n) 
         ostringstream_content << &response; 
     } 

     if (error == boost::asio::error::eof) 
       break; 

     if (error) 
       return -1; //throw boost::system::system_error(error); 
} 

str_response_ = ostringstream_content.str(); 

は、しかし、私はこの

1 [5a0 
    2 {"a_token":"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0Nzk5Mjk2NjcsIn...030"} 
    3 0 
    4 
    5 ] 

[と]を読んでいますされ、対応を開始し、データの終わりをデバッグするために私のコードからマークされています。私は1行目に問題のある文字が3つ以上あります。つまり、正しい2行目のjson文字列である5a0、そして はゼロと空白行です。どのようにしてjson文字列だけを正確に取得できますか?

答えて

1

私はあなたの例を書き直しました。それは私のためにうまくいきます。私はレスポンスを読むためのいくつかのショートカットを作ったことに注意してください。

Python 2.7.10 (default, Jul 14 2015, 19:46:27) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import socket as s 
>>> sd = s.socket(s.AF_INET, s.SOCK_STREAM) 
>>> sd.bind(("127.0.0.1", 8000)) 
>>> sd.listen(1) 
>>> c, a = sd.accept() 
>>> resp = "HTTP/1.1 200 OK\nDate: Fri, 31 Dec 1999 23:59:59 GMT\nContent-Type: text/plain\nTransfer-Encoding: chunked\n\r\n\r\n{\"token\":\"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0Nzk5Mjk2NjcsIn...030\"}" 
>>> c.send(resp) 
173 
>>> exit() 

ASIO出力:

MacBook-Pro:asio_test amuralid$ ./json_read_so 
Request sent 
V : HTTP/1.1 
H: Date: Fri, 31 Dec 1999 23:59:59 GMT 
H: Content-Type: text/plain 
H: Transfer-Encoding: chunked 

{"token":"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0Nzk5Mjk2NjcsIn...030"} 
私は

#include <asio.hpp> 
#include <iostream> 
#include <sstream> 
#include <istream> 

int main(int argc, const char * argv[]) { 

    static asio::io_service ios; 
    asio::ip::tcp::endpoint 
    endpoint(asio::ip::address::from_string("127.0.0.1"), 8000); 
    asio::generic::stream_protocol::socket socket{ios}; 
    socket.connect(endpoint); 

    std::string req = "GET /api\n\r\n\r\n"; 
    std::error_code ec; 
    socket.write_some(asio::buffer(req, req.size()), ec); 
    std::cout << "Request sent" << std::endl; 

    if (ec == asio::error::eof) { 
     std::cerr << "Premature termination\n"; 
     return 1; 
    } 
    //while (true) { 
    { 
      asio::streambuf response; 
      // Get till all the headers 
      asio::read_until(socket, response, "\r\n\r\n"); 

      // Check that response is OK. 
      std::istream response_stream(&response); 
      std::string http_version; 
      response_stream >> http_version; 
      std::cout << "V : " << http_version << std::endl; 

      unsigned int status_code; 
      response_stream >> status_code; 

      std::string status_message; 
      std::getline(response_stream, status_message); 

      if (!response_stream || http_version.substr(0, 5) != "HTTP/") { 
      std::cerr << "invalid response"; 
      return -1; 
      } 

      if (status_code != 200) { 
      std::cerr << "response did not returned 200 but " << status_code; 
      return -1; 
      } 

      //read the headers. 
      std::string header; 
      while (std::getline(response_stream, header) && header != "\r") { 
      std::cout << "H: " << header << std::endl; 
      } 

      std::ostringstream ostringstream_content; 
      if (response.size() > 0) { 
      ostringstream_content << &response; 
      } 

      std::error_code error; 
      while (true) { 
      size_t n = asio::read(socket, response, asio::transfer_at_least(1), error); 
      if (!error) { 
       if (n) { 
        ostringstream_content << &response; 
       } 
      } 

      if (error == asio::error::eof) { 
       break; 
      } 
      if (error) { 
       return -1; //throw boost::system::system_error(error); 
      } 
      } 
      auto str_response = ostringstream_content.str(); 
      std::cout << str_response << std::endl; 
    } 

    //} 

    return 0; 
} 

とテストのための私のpythonサーバ(純粋な怠惰のうちの)個別に読み込むのではなく、1回のショットでのステータス行とヘッダを読んでいます

+0

変更しましたか?私は多かれ少なかれ同じコードを使用していると思います。 – cateof

+1

ヘッダ解析以外は何もありません。また、私はasioのスタンドアロンバージョンを使用しています。うまくいけば、何の違いもありません。 – Arunmu

+0

@cateof上記のような完全な例を与えることができれば、おそらく分かりやすいでしょう。 – Arunmu

関連する問題