5
// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15
#include <boost/asio.hpp>
16
#include <boost/bind.hpp>
18
using boost::asio::ip::tcp;
23
client(boost::asio::io_service& io_service,
24
const std::string& server, const std::string& path)
25
: resolver_(io_service),
28
// Form the request. We specify the "Connection: close" header so that the
29
// server will close the socket after transmitting the response. This will
30
// allow us to treat all data up until the EOF as the content.
31
std::ostream request_stream(&request_);
32
request_stream << "GET " << path << " HTTP/1.0\r\n";
33
request_stream << "Host: " << server << "\r\n";
34
request_stream << "Accept: */*\r\n";
35
request_stream << "Connection: close\r\n\r\n";
37
// Start an asynchronous resolve to translate the server and service names
38
// into a list of endpoints.
39
tcp::resolver::query query(server, "http");
40
resolver_.async_resolve(query,
41
boost::bind(&client::handle_resolve, this,
42
boost::asio::placeholders::error,
43
boost::asio::placeholders::iterator));
47
void handle_resolve(const boost::system::error_code& err,
48
tcp::resolver::iterator endpoint_iterator)
52
// Attempt a connection to each endpoint in the list until we
53
// successfully establish a connection.
54
boost::asio::async_connect(socket_, endpoint_iterator,
55
boost::bind(&client::handle_connect, this,
56
boost::asio::placeholders::error));
60
std::cout << "Error: " << err.message() << "\n";
64
void handle_connect(const boost::system::error_code& err)
68
// The connection was successful. Send the request.
69
boost::asio::async_write(socket_, request_,
70
boost::bind(&client::handle_write_request, this,
71
boost::asio::placeholders::error));
75
std::cout << "Error: " << err.message() << "\n";
79
void handle_write_request(const boost::system::error_code& err)
83
// Read the response status line. The response_ streambuf will
84
// automatically grow to accommodate the entire line. The growth may be
85
// limited by passing a maximum size to the streambuf constructor.
86
boost::asio::async_read_until(socket_, response_, "\r\n",
87
boost::bind(&client::handle_read_status_line, this,
88
boost::asio::placeholders::error));
92
std::cout << "Error: " << err.message() << "\n";
96
void handle_read_status_line(const boost::system::error_code& err)
100
// Check that response is OK.
101
std::istream response_stream(&response_);
102
std::string http_version;
103
response_stream >> http_version;
104
unsigned int status_code;
105
response_stream >> status_code;
106
std::string status_message;
107
std::getline(response_stream, status_message);
108
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
110
std::cout << "Invalid response\n";
113
if (status_code != 200)
115
std::cout << "Response returned with status code ";
116
std::cout << status_code << "\n";
120
// Read the response headers, which are terminated by a blank line.
121
boost::asio::async_read_until(socket_, response_, "\r\n\r\n",
122
boost::bind(&client::handle_read_headers, this,
123
boost::asio::placeholders::error));
127
std::cout << "Error: " << err << "\n";
131
void handle_read_headers(const boost::system::error_code& err)
135
// Process the response headers.
136
std::istream response_stream(&response_);
138
while (std::getline(response_stream, header) && header != "\r")
139
std::cout << header << "\n";
142
// Write whatever content we already have to output.
143
if (response_.size() > 0)
144
std::cout << &response_;
146
// Start reading remaining data until EOF.
147
boost::asio::async_read(socket_, response_,
148
boost::asio::transfer_at_least(1),
149
boost::bind(&client::handle_read_content, this,
150
boost::asio::placeholders::error));
154
std::cout << "Error: " << err << "\n";
158
void handle_read_content(const boost::system::error_code& err)
162
// Write all of the data that has been read so far.
163
std::cout << &response_;
165
// Continue reading remaining data until EOF.
166
boost::asio::async_read(socket_, response_,
167
boost::asio::transfer_at_least(1),
168
boost::bind(&client::handle_read_content, this,
169
boost::asio::placeholders::error));
171
else if (err != boost::asio::error::eof)
173
std::cout << "Error: " << err << "\n";
177
tcp::resolver resolver_;
179
boost::asio::streambuf request_;
180
boost::asio::streambuf response_;
183
int main(int argc, char* argv[])
189
std::cout << "Usage: async_client <server> <path>\n";
190
std::cout << "Example:\n";
191
std::cout << " async_client www.boost.org /LICENSE_1_0.txt\n";
195
boost::asio::io_service io_service;
196
client c(io_service, argv[1], argv[2]);
199
catch (std::exception& e)
201
std::cout << "Exception: " << e.what() << "\n";