Skip to content

Instantly share code, notes, and snippets.

@hecomi
Last active December 10, 2015 11:19
Show Gist options
  • Save hecomi/4426931 to your computer and use it in GitHub Desktop.
Save hecomi/4426931 to your computer and use it in GitHub Desktop.
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/thread.hpp>
#include <boost/system/system_error.hpp>
#include <iostream>
using namespace std;
namespace asio = boost::asio;
using boost::asio::ip::tcp;
class Client {
typedef boost::function<void(const string&, const string&)> callback;
callback callback_;
string host_;
string html_;
asio::io_service& io_service_;
tcp::socket socket_;
tcp::resolver resolver_;
asio::streambuf buf_;
public:
Client(asio::io_service& io_service)
: io_service_(io_service),
socket_(io_service),
resolver_(io_service)
{}
void get(const string& host, callback callback)
{
host_ = host;
callback_ = callback;
html_ = "";
tcp::resolver::query query(host, "http");
resolver_.async_resolve(
query,
boost::bind(
&Client::on_resolve,
this,
asio::placeholders::error,
asio::placeholders::iterator));
boost::thread t(boost::bind(&asio::io_service::run, &io_service_));
t.detach();
}
private:
void on_resolve(const boost::system::error_code& error,
tcp::resolver::iterator endpoint_iterator)
{
if (has_error(error)) return;
async_connect(
socket_,
endpoint_iterator,
boost::bind(&Client::on_connect, this, asio::placeholders::error));
}
void on_connect(const boost::system::error_code& error)
{
if (has_error(error)) return;
buf_.consume(buf_.size());
ostream s(&buf_);
s << "GET / HTTP/1.0\r\n";
s << "Host: " << host_ << "\r\n";
s << "\r\n";
async_write(
socket_,
buf_,
boost::bind(&Client::on_write, this, asio::placeholders::error));
}
void on_write(const boost::system::error_code& error)
{
if (has_error(error)) return;
buf_.consume(buf_.size());
async_read(
socket_,
buf_,
asio::transfer_at_least(1),
boost::bind(&Client::on_receive, this, asio::placeholders::error));
}
void on_receive(const boost::system::error_code& error)
{
if (error.message().find("End of file") != std::string::npos) {
callback_("", html_);
return;
}
if (has_error(error)) return;
const string data(asio::buffer_cast<const char*>(buf_.data()), buf_.size());
buf_.consume(buf_.size());
html_ += data;
async_read(
socket_,
buf_,
asio::transfer_at_least(1),
boost::bind(&Client::on_receive, this, asio::placeholders::error));
}
bool has_error(const boost::system::error_code& error)
{
if (error) {
callback_(error.message(), html_);
return true;
}
return false;
}
};
int main()
{
asio::io_service io_service;
Client client(io_service);
const string url = "www.google.co.jp";
client.get(url, [](const string& error, const string& html) {
if (!error.empty()) {
std::cerr << error << std::endl;
return;
}
cout << html << endl;
});
// 何か処理
boost::this_thread::sleep_for(boost::chrono::seconds(5));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment