基于BOOST :: ASIO-慢慢http客户端 - (转移块)
slow http client based on boost::asio - (Chunked Transfer)
我正在使用以下代码(从Boost教程中获取)从服务器中获取JSON字符串。
问题在于执行需要一些时间,即完成超过2秒钟才能完成,并且客户端和服务器都在Localhost上。如果我删除程序的最后2行,则为此处:
while(boost :: asio :: read(套接字,响应, boost :: asio :: trasse_at_least(1),错误))
该程序执行非常快。问题可能是什么?
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "rn");
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/")
{
std::cout << "Invalid responsen";
return 1;
}
if (status_code != 200)
{
std::cout << "Response returned with status code " << status_code << "n";
return 1;
}
boost::asio::read_until(socket, response, "rnrn");
// Process the response headers.
std::string header;
while (std::getline(response_stream, header) && header != "r");
if (response.size() > 0)
std::cout << &response;
// Read until EOF, writing data to output as we go.
boost::system::error_code error;
while (boost::asio::read(socket, response,
boost::asio::transfer_at_least(1), error))
std::cout << &response;
if (error != boost::asio::error::eof)
throw boost::system::system_error(error);
tcpdump显示从服务器显示一些数据
HTTP/1.1 200 OK
Connection: close
Content-Length: 42
Server: C/1.1
Date: Thu, 24 Nov 2016 07:47:27 GMT
{"Out":[1],"In":[1,2,3,4,5,6]}
从评论中的讨论中可以理解,主要问题是阅读块数据。对于HTTP块编码的数据,在块数据开始之前,大小在十六进制中前缀。因此,必须读取大小是该块的内容长度。
asio::streambuf response;
// Get till all the headers
asio::read_until(socket, response, "rnrn");
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
std::cout << "Version : " << 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;
}
bool chunk_size_present = false;
std::string chunk_siz_str;
// Ignore the remaining additional 'rn' after the header
std::getline(response_stream, header);
// Read the Chunk size
asio::read_until(socket, response, "rn");
std::getline(response_stream, chunk_siz_str);
std::cout << "CS : " << chunk_siz_str << std::endl;
size_t chunk_size = (int)strtol(chunk_siz_str.c_str(), nullptr, 16);
// Now how many bytes yet to read from the socket ?
// response might have some additional data still with it
// after the last `read_until`
auto chunk_bytes_to_read = chunk_size - response.size();
std::cout << "Chunk Length = " << chunk_size << std::endl;
std::cout << "Additional bytes to read: " << response_stream.gcount() << std::endl;
std::error_code error;
size_t n = asio::read(socket, response, asio::transfer_exactly(chunk_bytes_to_read), error);
if (error) {
return -1; //throw boost::system::system_error(error);
}
std::ostringstream ostringstream_content;
ostringstream_content << &response;
auto str_response = ostringstream_content.str();
std::cout << str_response << std::endl;
有点棘手的部分是asio::read_until
保证它可以将数据读取到提供的模式,但也可以将更多数据读取到缓冲区中。
http中唯一的" eof"是关闭TCP连接时。在这种情况下,您很幸运,服务器在关闭连接之前仅在2秒钟后就开始了 - 否则,您的应用程序将坐着更长的时间。
您需要使用Content-Length
值来了解要读取多少数据,而不是寻找EOF条件。
Google" HTTP管道"为了理解为什么当您期望它时服务器未关闭TCP连接。
相关文章:
- 如何在boost beast http请求中设置http头
- 在多个核心中处理一个HTTP请求
- SFML library: http request
- 我是否需要在下一次转移时将所有权*转移回转移队列
- 如何将元素从向量转移到新数组?
- 使用 Winsock2.h C++向不和谐 API 发送 HTTP 请求时出现问题
- 为什么系统函数总是在C++中返回已转移的退出状态?
- 通过单独的 tcp 流建立 http 连接
- 使用 winsock 接收 http 请求
- 如何在 c++ 中通过 http 发送大型视频文件?
- 对于 http 请求,python 比 c++ 快吗?
- 使用 c++ 的 http 客户端的默认方法
- 如何使用C++和Boost Asio从HTTP发布请求中获取键值
- 如何使用boost/beast从HTTP POST请求中解析和提取有效负载?
- 如何重用 http::beast::flat_buffer 和 http::response?
- 在客户端和备忘录中获取 HTTP 命令
- C++:将 UDP 袜子转移到新位置
- 在C ++ ASIO中,如何为HTTP或HTTPS创建相同的套接字对象(接口/抽象问题?
- HTTP 响应格式不正确?
- 基于BOOST :: ASIO-慢慢http客户端 - (转移块)