基于行的操作

许多的协议都是基于行的,这意味着它们是由包含“\r\n”的字符串构成的。例如HTTP,SMTP和FTP。为了更简单地完成这类协议,Asio提供了函数 read_until()和 async_read_until()。

如下例子展示了 async_read_until()是如何接收HTTP服务器端是如何接收一个HTTP请求的:

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_;
};

streambuf数据成员存放了从socket读到的,两个分界符之间的数据。切记,在分界符之后,很有可能还有额外的数据。这些多余的数据应该被留在streambuf中以便随后的read_until()或者async_read_until()。

分界符可能是单一的字符,一个std::string或者boost::regex(译者注:boost库的正则表达式)。read_until()和async_read_until()可以重载以支持自定义的类型。例如读到空白字符:

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);

又比如读到指定的字符:

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’));

is_match_condition<>对象会自动求值为true(译者注:此处原文为 trait automatically evaluates to true for functions),而且给函数对象(译者注:此处为仿函数)一个嵌套的返回值。如果使用其他类型,需要显式地声明该特性,就像上面那样。

参见

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

results matching ""

    No results matching ""