* HttpBoostCL.h
*
* Created on: 2018年4月10日
* Author: Administrator
*/
#ifndef BOOSTSTUDY_HTTPBOOSTCL_H_
#define BOOSTSTUDY_HTTPBOOSTCL_H_
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class BoostHttpClient
{
public:
BoostHttpClient();
~BoostHttpClient();
static int boost_http_sync_client(const std::string& server, const std::string& port, const std::string& path,
std::string& out_response_status_line, std::string& out_response_header, std::string& out_response_data);
static int parse_url(const std::string& url, std::string& out_server, std::string& out_port, std::string& out_path);
static int get_url_response(const std::string& url, std::string& out_response_data);
};
#endif /* BOOSTSTUDY_HTTPBOOSTCL_H_ */
/*
* HttpBoostCL.cpp
*
* Created on: 2018年4月10日
* Author: Administrator
*/
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include "HttpBoostCL.h"
int64_t getTimeMsec()
{
struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
BoostHttpClient::BoostHttpClient()
{
}
BoostHttpClient::~BoostHttpClient()
{
}
int BoostHttpClient::boost_http_sync_client(const std::string& server,
const std::string& port, const std::string& path,
std::string& out_response_status_line, std::string& out_response_header,
std::string& out_response_data)
{
try
{
boost::asio::io_service io_service;
// Get a list of endpoints corresponding to the server name.
tcp::resolver resolver(io_service);
tcp::resolver::query query(server, port/*"http"*/);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
// Try each endpoint until we successfully establish a connection.
tcp::socket socket_(io_service);
boost::asio::connect(socket_, endpoint_iterator);
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "GET " << path/*argv[2]*/<< " HTTP/1.0\r\n";
request_stream << "Host: " << server/*argv[1]*/<< "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
std::cout << "write begin" << getTimeMsec() << std::endl;
// Send the request.
boost::asio::write(socket_, request);
std::cout << "write end" << getTimeMsec() << std::endl;
// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing
// a maximum size to the streambuf constructor.
boost::asio::streambuf response;
boost::asio::read_until(socket_, response, "\r\n");
if (true)
{
boost::asio::streambuf::const_buffers_type cbt = response.data();
std::string temp_data(boost::asio::buffers_begin(cbt),
boost::asio::buffers_end(cbt));
std::size_t idx = temp_data.find('\n');
idx == std::string::npos ? temp_data.size() : idx;
out_response_status_line = temp_data.substr(0, idx + 1);
}
// 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/")
{
std::cout << "Invalid response\n";
return 1;
}
if (status_code != 200)
{
std::cout << "Response returned with status code " << status_code
<< "\n";
return 1;
}
// Read the response headers, which are terminated by a blank line.
boost::asio::read_until(socket_, response, "\r\n\r\n");
if (true)
{
boost::asio::streambuf::const_buffers_type cbt = response.data();
std::string temp_data(boost::asio::buffers_begin(cbt),
boost::asio::buffers_end(cbt));
std::size_t idx = temp_data.find("\r\n\r\n");
idx == std::string::npos ? temp_data.length() : idx;
out_response_header = temp_data.substr(0, idx + 2);
}
// Process the response headers.
std::string header;
while (std::getline(response_stream, header) && header != "\r")
; //std::cout << header << "\n";
//std::cout << "\n";
// Write whatever content we already have to output.
//if (response.size() > 0)
// std::cout << &response;
if (true)
{
boost::asio::streambuf::const_buffers_type cbt = response.data();
out_response_data = std::string(boost::asio::buffers_begin(cbt),
boost::asio::buffers_end(cbt));
}
// 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;
{
boost::asio::streambuf::const_buffers_type cbt = response.data();
out_response_data += std::string(boost::asio::buffers_begin(cbt),
boost::asio::buffers_end(cbt));
}
if (error != boost::asio::error::eof)
throw boost::system::system_error(error);
//socket_.cancel();
} catch (std::exception& e)
{
std::cout << "Exception: " << e.what() << "\n";
return -1;
}
return 0;
}
int BoostHttpClient::parse_url(const std::string& url,
std::string& out_server, std::string& out_port, std::string& out_path)
{
const std::string http___ = "http://";
const std::string https___ = "https://";
std::string temp_data = url;
if (temp_data.find(http___) == 0)
temp_data = temp_data.substr(http___.length());
else if (temp_data.find(https___) == 0)
temp_data = temp_data.substr(https___.length());
else
return -1;
std::size_t idx = temp_data.find('/');
if (std::string::npos == idx)
{
out_path = "/";
idx = temp_data.size();
}
else
{
out_path = temp_data.substr(idx);
}
out_server = temp_data.substr(0, idx);
idx = out_server.find(':');
if (std::string::npos == idx)
{
out_port = "http";
out_port = "80";
}
else
{
out_port = out_server.substr(idx + 1);
out_server = out_server.substr(0, idx);
}
return 0;
}
//
int BoostHttpClient::get_url_response(const std::string& url, std::string& out_response_data)
{
int rv = 0;
do
{
std::string server;
std::string port;
std::string path;
rv = parse_url(url, server, port, path);
if (rv) break;
std::string out_response_status_line;
std::string out_response_header;
rv = boost_http_sync_client(server, port, path, out_response_status_line, out_response_header, out_response_data);
if (rv) break;
} while (false);
return rv;
}
int main()
{
int rv = 0;
std::string url = "http://hq.sinajs.cn/list=sh204001";
while(1)
{
int64_t timeBegin = getTimeMsec();
std::string response_data;
rv = BoostHttpClient::get_url_response(url, response_data);
int64_t timeEnd = getTimeMsec();
if (rv) return -1;
std::cout << "timeuse:"<< timeEnd-timeBegin << "res:"<< response_data << std::endl;
sleep(1);
}
return 0;
}
//g++ HttpBoostCL.cpp -o httptest -lpthread -lboost_system