]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/ |
2 | / Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) | |
3 | / | |
4 | / Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | /] | |
7 | ||
8 | [section:line_based Line-Based Operations] | |
9 | ||
10 | Many commonly-used internet protocols are line-based, which means that they | |
11 | have protocol elements that are delimited by the character sequence `"\r\n"`. | |
12 | Examples include HTTP, SMTP and FTP. To more easily permit the implementation | |
13 | of line-based protocols, as well as other protocols that use delimiters, Boost.Asio | |
14 | includes the functions `read_until()` and `async_read_until()`. | |
15 | ||
16 | The following example illustrates the use of `async_read_until()` in an HTTP | |
17 | server, to receive the first line of an HTTP request from a client: | |
18 | ||
19 | class http_connection | |
20 | { | |
21 | ... | |
22 | ||
23 | void start() | |
24 | { | |
25 | boost::asio::async_read_until(socket_, data_, "\r\n", | |
26 | boost::bind(&http_connection::handle_request_line, this, _1)); | |
27 | } | |
28 | ||
29 | void handle_request_line(boost::system::error_code ec) | |
30 | { | |
31 | if (!ec) | |
32 | { | |
33 | std::string method, uri, version; | |
34 | char sp1, sp2, cr, lf; | |
35 | std::istream is(&data_); | |
36 | is.unsetf(std::ios_base::skipws); | |
37 | is >> method >> sp1 >> uri >> sp2 >> version >> cr >> lf; | |
38 | ... | |
39 | } | |
40 | } | |
41 | ||
42 | ... | |
43 | ||
44 | boost::asio::ip::tcp::socket socket_; | |
45 | boost::asio::streambuf data_; | |
46 | }; | |
47 | ||
48 | The `streambuf` data member serves as a place to store the data that has been | |
49 | read from the socket before it is searched for the delimiter. It is important | |
50 | to remember that there may be additional data ['after] the delimiter. This | |
51 | surplus data should be left in the `streambuf` so that it may be inspected by a | |
52 | subsequent call to `read_until()` or `async_read_until()`. | |
53 | ||
54 | The delimiters may be specified as a single `char`, a `std::string` or a | |
55 | `boost::regex`. The `read_until()` and `async_read_until()` functions also | |
56 | include overloads that accept a user-defined function object called a match | |
57 | condition. For example, to read data into a streambuf until whitespace is | |
58 | encountered: | |
59 | ||
60 | typedef boost::asio::buffers_iterator< | |
61 | boost::asio::streambuf::const_buffers_type> iterator; | |
62 | ||
63 | std::pair<iterator, bool> | |
64 | match_whitespace(iterator begin, iterator end) | |
65 | { | |
66 | iterator i = begin; | |
67 | while (i != end) | |
68 | if (std::isspace(*i++)) | |
69 | return std::make_pair(i, true); | |
70 | return std::make_pair(i, false); | |
71 | } | |
72 | ... | |
73 | boost::asio::streambuf b; | |
74 | boost::asio::read_until(s, b, match_whitespace); | |
75 | ||
76 | To read data into a streambuf until a matching character is found: | |
77 | ||
78 | class match_char | |
79 | { | |
80 | public: | |
81 | explicit match_char(char c) : c_(c) {} | |
82 | ||
83 | template <typename Iterator> | |
84 | std::pair<Iterator, bool> operator()( | |
85 | Iterator begin, Iterator end) const | |
86 | { | |
87 | Iterator i = begin; | |
88 | while (i != end) | |
89 | if (c_ == *i++) | |
90 | return std::make_pair(i, true); | |
91 | return std::make_pair(i, false); | |
92 | } | |
93 | ||
94 | private: | |
95 | char c_; | |
96 | }; | |
97 | ||
98 | namespace boost { namespace asio { | |
99 | template <> struct is_match_condition<match_char> | |
100 | : public boost::true_type {}; | |
101 | } } // namespace boost::asio | |
102 | ... | |
103 | boost::asio::streambuf b; | |
104 | boost::asio::read_until(s, b, match_char('a')); | |
105 | ||
106 | The `is_match_condition<>` type trait automatically evaluates to true for | |
107 | functions, and for function objects with a nested `result_type` typedef. For | |
108 | other types the trait must be explicitly specialised, as shown above. | |
109 | ||
110 | [heading See Also] | |
111 | ||
112 | [link boost_asio.reference.async_read_until async_read_until()], | |
113 | [link boost_asio.reference.is_match_condition is_match_condition], | |
114 | [link boost_asio.reference.read_until read_until()], | |
115 | [link boost_asio.reference.streambuf streambuf], | |
116 | [link boost_asio.examples.cpp03_examples.http_client HTTP client example]. | |
117 | ||
118 | [endsect] |