summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/src/doc/overview/line_based.qbk
blob: df007adc3f83f7b8e7d22082911a564f4fc8e113 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
[/
 / Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 /
 / Distributed under the Boost Software License, Version 1.0. (See accompanying
 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 /]

[section:line_based Line-Based Operations]

Many commonly-used internet protocols are line-based, which means that they
have protocol elements that are delimited by the character sequence `"\r\n"`.
Examples include HTTP, SMTP and FTP. To more easily permit the implementation
of line-based protocols, as well as other protocols that use delimiters, Asio
includes the functions `read_until()` and `async_read_until()`.

The following example illustrates the use of `async_read_until()` in an HTTP
server, to receive the first line of an HTTP request from a client:

  class http_connection
  {
    ...

    void start()
    {
      asio::async_read_until(socket_, data_, "\r\n",
          boost::bind(&http_connection::handle_request_line, this, _1));
    }

    void handle_request_line(asio::error_code ec)
    {
      if (!ec)
      {
        std::string method, uri, version;
        char sp1, sp2, cr, lf;
        std::istream is(&data_);
        is.unsetf(std::ios_base::skipws);
        is >> method >> sp1 >> uri >> sp2 >> version >> cr >> lf;
        ...
      }
    }

    ...

    asio::ip::tcp::socket socket_;
    asio::streambuf data_;
  };

The `streambuf` data member serves as a place to store the data that has been
read from the socket before it is searched for the delimiter. It is important
to remember that there may be additional data ['after] the delimiter. This
surplus data should be left in the `streambuf` so that it may be inspected by a
subsequent call to `read_until()` or `async_read_until()`.

The delimiters may be specified as a single `char`, a `std::string` or a
`boost::regex`. The `read_until()` and `async_read_until()` functions also
include overloads that accept a user-defined function object called a match
condition. For example, to read data into a streambuf until whitespace is
encountered:

  typedef asio::buffers_iterator<
      asio::streambuf::const_buffers_type> iterator;

  std::pair<iterator, bool>
  match_whitespace(iterator begin, iterator end)
  {
    iterator i = begin;
    while (i != end)
      if (std::isspace(*i++))
        return std::make_pair(i, true);
    return std::make_pair(i, false);
  }
  ...
  asio::streambuf b;
  asio::read_until(s, b, match_whitespace);

To read data into a streambuf until a matching character is found:

  class match_char
  {
  public:
    explicit match_char(char c) : c_(c) {}

    template <typename Iterator>
    std::pair<Iterator, bool> operator()(
        Iterator begin, Iterator end) const
    {
      Iterator i = begin;
      while (i != end)
        if (c_ == *i++)
          return std::make_pair(i, true);
      return std::make_pair(i, false);
    }

  private:
    char c_;
  };

  namespace asio {
    template <> struct is_match_condition<match_char>
      : public boost::true_type {};
  } // namespace asio
  ...
  asio::streambuf b;
  asio::read_until(s, b, match_char('a'));

The `is_match_condition<>` type trait automatically evaluates to true for
functions, and for function objects with a nested `result_type` typedef. For
other types the trait must be explicitly specialised, as shown above.

[heading See Also]

[link asio.reference.async_read_until async_read_until()],
[link asio.reference.is_match_condition is_match_condition],
[link asio.reference.read_until read_until()],
[link asio.reference.streambuf streambuf],
[link asio.examples.cpp03_examples.http_client HTTP client example].

[endsect]