[关闭]
@john-lee 2021-01-03T02:41:31.000000Z 字数 2073 阅读 674

基于行的操作(Line-Based Operations)

Boost.Asio


许多常用的 internet 协议是基于行的,这意味着它们具有由字符序列“\r\n”分隔的协议元素。例如 HTTP、SMTP 和 FTP。为了更容易地实现基于行的协议以及使用分隔符的其他协议,Boost.Asio 包括函数read_until()async_read_until()

下面的示例说明如何在 HTTP 服务器中使用async_read_until()从客户端接收 HTTP 请求的第一行:

  1. class http_connection
  2. {
  3. ...
  4. void start()
  5. {
  6. boost::asio::async_read_until(socket_, data_, "\r\n",
  7. boost::bind(&http_connection::handle_request_line, this, _1));
  8. }
  9. void handle_request_line(boost::system::error_code ec)
  10. {
  11. if (!ec)
  12. {
  13. std::string method, uri, version;
  14. char sp1, sp2, cr, lf;
  15. std::istream is(&data_);
  16. is.unsetf(std::ios_base::skipws);
  17. is >> method >> sp1 >> uri >> sp2 >> version >> cr >> lf;
  18. ...
  19. }
  20. }
  21. ...
  22. boost::asio::ip::tcp::socket socket_;
  23. boost::asio::streambuf data_;
  24. };

streambuf数据成员用作存储在搜索分隔符之前从套接字读取的数据的位置。请务必记住,分隔符后面可能还有其他数据。剩余的数据应该留在streambuf中,以便后续的read_until()async_read_until()调用可以检查它。

分隔符可以指定为单个charstd::stringboost::regexread_until()async_read_until()函数还包括接受称为匹配条件的用户定义函数对象的重载。例如,将数据读取到streambuf,直到遇到空白:

  1. typedef boost::asio::buffers_iterator<
  2. boost::asio::streambuf::const_buffers_type> iterator;
  3. std::pair<iterator, bool>
  4. match_whitespace(iterator begin, iterator end)
  5. {
  6. iterator i = begin;
  7. while (i != end)
  8. if (std::isspace(*i++))
  9. return std::make_pair(i, true);
  10. return std::make_pair(i, false);
  11. }
  12. ...
  13. boost::asio::streambuf b;
  14. boost::asio::read_until(s, b, match_whitespace);

要将数据读取到streambuf中,直到找到匹配的字符:

  1. class match_char
  2. {
  3. public:
  4. explicit match_char(char c) : c_(c) {}
  5. template <typename Iterator>
  6. std::pair<Iterator, bool> operator()(
  7. Iterator begin, Iterator end) const
  8. {
  9. Iterator i = begin;
  10. while (i != end)
  11. if (c_ == *i++)
  12. return std::make_pair(i, true);
  13. return std::make_pair(i, false);
  14. }
  15. private:
  16. char c_;
  17. };
  18. namespace boost { namespace asio {
  19. template <> struct is_match_condition<match_char>
  20. : public boost::true_type {};
  21. } } // namespace boost::asio
  22. ...
  23. boost::asio::streambuf b;
  24. boost::asio::read_until(s, b, match_char('a'));

对于函数和typedef的嵌套result_type类型的函数对象,is_match_condition<>类型特征会自动计算为 true。对于其他类型的特征必须明确特化,如上所示。

另请参阅

async_read_until()、is_match_condition read_until()、streambuf、HTTP 客户端示例。


Copyright © 2003-2020 Christopher M. Kohlhoff

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)

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注