使用 Boost.ASIO [WebSocket] 完整阅读消息

Posted

技术标签:

【中文标题】使用 Boost.ASIO [WebSocket] 完整阅读消息【英文标题】:Read message in its entirety with Boost.ASIO [WebSocket] 【发布时间】:2015-01-27 21:02:50 【问题描述】:

我正在使用 Boost.ASIO 编写一个简单的 WebSocket 服务器。现在,我正在努力尝试处理握手。我的问题是,客户端发送的握手消息似乎没有预定义的长度。

我的问题是,我怎样才能在消息结束时停止阅读握手?

我首先尝试了 async_read_some,我在其中读取了指定的字节数。

void Connection::readMessage()

    auto self(shared_from_this());
    w_socket.async_read_some(boost::asio::buffer(w_data, max_length),
        [this, self](boost::system::error_code ec, std::size_t length)  // Lambda function
        
            if (!ec)
            
                std::cout << w_data << std::endl;
            
        );

上面的代码给了我这个结果: http://i.imgur.com/LSyfG2U.png

然后我尝试进一步研究,发现 async_read_until(读取直到找到连续的新行)暂时修复了握手消息,但这并不能保证它会停止。

void Connection::readMessage()

    auto self(shared_from_this());
    boost::asio::async_read_until(w_socket, streambuffer, "\r\n\r\n",
        [this, self](boost::system::error_code ec, std::size_t length)  // Lambda function
        
            if (!ec)
            
                std::istream is(&streambuffer);
                std::getline(is, w_data_s);

                std::cout << w_data_s << std::endl;
            
        );

上面的代码给出了这个结果:http://i.imgur.com/JW1dyLH.png

或者更好的问题是,哪个最适合处理握手消息,哪个最适合在握手通过后处理普通消息(数据帧和其他东西)。

【问题讨论】:

【参考方案1】:

在此处查看 websocket 规范:http://datatracker.ietf.org/doc/rfc6455/?include_text=1 您走在正确的轨道上。

使用 async_read_until 来处理握手,因为它具有未定义的长度,但与 http 的分隔符相同,然后,在完成握手后,个人为了交换实际数据,切换到使用 async_read 使用任一固定长度的预定义标头它描述了后续正文的长度,或指定您自己的完成条件。如果您不介意以某种固定方式分隔消息,您当然可以继续使用 async_read_until。

【讨论】:

非常感谢,奥利弗。我质疑使用 async_read_until 的唯一原因是因为我觉得有人会利用它通过一种方式让读者继续阅读而无意结束。不过,这可能是添加超时计时器以防止此类攻击的好地方。

以上是关于使用 Boost.ASIO [WebSocket] 完整阅读消息的主要内容,如果未能解决你的问题,请参考以下文章

使用 boost::asio::async_wait_until 和 boost::asio::streambuf

std::boost::asio::post / dispatch 使用哪个 io_context?

将 Boost.Log 与 Boost.Asio 服务一起使用

使用 boost::asio 丢弃数据

传递给 boost::asio::async_read_some 的回调从未在 boost::asio::read_some 返回数据的使用中调用

使用 boost::asio::spawn 生成的 asio 处理程序中的 boost::property_tree::read_xml 段错误