基于行的操作

许多常用的互联网协议是基于行的,这意味着它们的协议元素由字符序列 "\r\n" 进行分隔。例如,HTTP、SMTP和FTP。为了更容易实现基于行的协议以及其他使用分隔符的协议,Boost.Asio 提供了 read_until() 和 async_read_until() 函数。

以下示例演示了在 HTTP 服务器中使用 async_read_until() 来接收来自客户端的 HTTP 请求的第一行:

class http_connection
{
  ...

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

  void handle_request_line(boost::system::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;
      ...
    }
  }

  ...

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

streambuf 数据成员用于存储从套接字读取的数据,以便在查找分隔符之前使用。重要的是要记住,在分隔符之后可能还有额外的数据。这些多余的数据应留在 streambuf 中,以便后续调用 read_until() 或 async_read_until() 进行检查。

分隔符可以指定为单个字符、std::string 或 boost::regex。read_until() 和 async_read_until() 函数还包括接受用户定义的函数对象作为匹配条件的重载。例如,要读取数据到 streambuf,直到遇到空白字符:

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

is_match_condition<> 类型特征会自动对函数和具有嵌套 result_type typedef 的函数对象评估为 true。如上所示,对于其他类型,特征必须显式特化。

See Also

async_read_until(), is_match_condition, read_until(), streambuf, HTTP client example.

Last updated