~ubuntu-branches/debian/sid/boost1.49/sid

« back to all changes in this revision

Viewing changes to doc/html/boost_asio/example/http/client/async_client.cpp

  • Committer: Package Import Robot
  • Author(s): Steve M. Robbins
  • Date: 2012-02-26 00:31:44 UTC
  • Revision ID: package-import@ubuntu.com-20120226003144-eaytp12cbf6ubpms
Tags: upstream-1.49.0
ImportĀ upstreamĀ versionĀ 1.49.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// async_client.cpp
 
3
// ~~~~~~~~~~~~~~~~
 
4
//
 
5
// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 
6
//
 
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)
 
9
//
 
10
 
 
11
#include <iostream>
 
12
#include <istream>
 
13
#include <ostream>
 
14
#include <string>
 
15
#include <boost/asio.hpp>
 
16
#include <boost/bind.hpp>
 
17
 
 
18
using boost::asio::ip::tcp;
 
19
 
 
20
class client
 
21
{
 
22
public:
 
23
  client(boost::asio::io_service& io_service,
 
24
      const std::string& server, const std::string& path)
 
25
    : resolver_(io_service),
 
26
      socket_(io_service)
 
27
  {
 
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";
 
36
 
 
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));
 
44
  }
 
45
 
 
46
private:
 
47
  void handle_resolve(const boost::system::error_code& err,
 
48
      tcp::resolver::iterator endpoint_iterator)
 
49
  {
 
50
    if (!err)
 
51
    {
 
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));
 
57
    }
 
58
    else
 
59
    {
 
60
      std::cout << "Error: " << err.message() << "\n";
 
61
    }
 
62
  }
 
63
 
 
64
  void handle_connect(const boost::system::error_code& err)
 
65
  {
 
66
    if (!err)
 
67
    {
 
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));
 
72
    }
 
73
    else
 
74
    {
 
75
      std::cout << "Error: " << err.message() << "\n";
 
76
    }
 
77
  }
 
78
 
 
79
  void handle_write_request(const boost::system::error_code& err)
 
80
  {
 
81
    if (!err)
 
82
    {
 
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));
 
89
    }
 
90
    else
 
91
    {
 
92
      std::cout << "Error: " << err.message() << "\n";
 
93
    }
 
94
  }
 
95
 
 
96
  void handle_read_status_line(const boost::system::error_code& err)
 
97
  {
 
98
    if (!err)
 
99
    {
 
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/")
 
109
      {
 
110
        std::cout << "Invalid response\n";
 
111
        return;
 
112
      }
 
113
      if (status_code != 200)
 
114
      {
 
115
        std::cout << "Response returned with status code ";
 
116
        std::cout << status_code << "\n";
 
117
        return;
 
118
      }
 
119
 
 
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));
 
124
    }
 
125
    else
 
126
    {
 
127
      std::cout << "Error: " << err << "\n";
 
128
    }
 
129
  }
 
130
 
 
131
  void handle_read_headers(const boost::system::error_code& err)
 
132
  {
 
133
    if (!err)
 
134
    {
 
135
      // Process the response headers.
 
136
      std::istream response_stream(&response_);
 
137
      std::string header;
 
138
      while (std::getline(response_stream, header) && header != "\r")
 
139
        std::cout << header << "\n";
 
140
      std::cout << "\n";
 
141
 
 
142
      // Write whatever content we already have to output.
 
143
      if (response_.size() > 0)
 
144
        std::cout << &response_;
 
145
 
 
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));
 
151
    }
 
152
    else
 
153
    {
 
154
      std::cout << "Error: " << err << "\n";
 
155
    }
 
156
  }
 
157
 
 
158
  void handle_read_content(const boost::system::error_code& err)
 
159
  {
 
160
    if (!err)
 
161
    {
 
162
      // Write all of the data that has been read so far.
 
163
      std::cout << &response_;
 
164
 
 
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));
 
170
    }
 
171
    else if (err != boost::asio::error::eof)
 
172
    {
 
173
      std::cout << "Error: " << err << "\n";
 
174
    }
 
175
  }
 
176
 
 
177
  tcp::resolver resolver_;
 
178
  tcp::socket socket_;
 
179
  boost::asio::streambuf request_;
 
180
  boost::asio::streambuf response_;
 
181
};
 
182
 
 
183
int main(int argc, char* argv[])
 
184
{
 
185
  try
 
186
  {
 
187
    if (argc != 3)
 
188
    {
 
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";
 
192
      return 1;
 
193
    }
 
194
 
 
195
    boost::asio::io_service io_service;
 
196
    client c(io_service, argv[1], argv[2]);
 
197
    io_service.run();
 
198
  }
 
199
  catch (std::exception& e)
 
200
  {
 
201
    std::cout << "Exception: " << e.what() << "\n";
 
202
  }
 
203
 
 
204
  return 0;
 
205
}