Boost Beast websocket 服务器异步接受失败,缓冲区溢出
Posted
技术标签:
【中文标题】Boost Beast websocket 服务器异步接受失败,缓冲区溢出【英文标题】:Boost beast websocket server async accept failed, buffer overflow 【发布时间】:2019-06-21 09:15:48 【问题描述】:我通过 boost asio websocket 编写了一个 websocket 服务器。 当我尝试将它与 chrome 连接时,它总是说连接失败。 并且日志显示缓冲区溢出。 尤其是在我打开很多网站之后。
[2019-06-21 16:40:45.071345]-[0x00003130]-[error]:[NormalSession.cpp:75] 接受器异步接受失败,ec = beast.http:7,msg = 缓冲区溢出
void NormalSession::run()
auto sp = shared_from_this();
ws_->async_accept(boost::asio::bind_executor(*strand_, [&,sp](boost::system::error_code ec)
if (ec)
LOG_ERR << "acceptor async accept failed, ec = " << ec<<", msg = "<<ec.message();
return;
process();
));
var ws=new WebSocket("ws://127.0.0.1:12802");
ws.onopen=()=>console.log('ws open');
ws.onclose=()=>console.log('ws close');
ws.onmessage=(msg)=>console.log('ws onMessage');console.log(msg);
那么为什么缓冲区溢出呢?以及如何解决?
完整代码
iListener.h
class iListener: public std::enable_shared_from_this<iListener>
public:
iListener(const std::string &, unsigned short , boost::asio::io_context& );
~iListener();
public:
void run();
protected:
virtual void do_accept()=0;
protected:
boost::asio::ip::tcp::acceptor *acceptor_=NULL;
;
iListener.cpp
iListener::iListener(const std::string &addressStr, unsigned short port, boost::asio::io_context &ioc)
acceptor_ = NULL;
auto const address = boost::asio::ip::make_address(addressStr);
acceptor_ = new boost::asio::ip::tcp::acceptor(ioc);
boost::asio::ip::tcp::endpoint endpointaddress, port;
boost::system::error_code ec;
// Open the acceptor
acceptor_->open(endpoint.protocol(), ec);
if (ec)
LOG_ERR << "acceptor open failed, ec = " << ec << ", msg = " << ec.message();
return;
// Allow address reuse
acceptor_->set_option(boost::asio::socket_base::reuse_address(true), ec);
if (ec)
LOG_ERR << "acceptor set option failed, ec = " << ec << ", msg = " << ec.message();
return;
// Bind to the server address
acceptor_->bind(endpoint, ec);
if (ec)
LOG_ERR << "acceptor bind failed, ec = " << ec << ", msg = " << ec.message();
return;
// Start listening for connections
acceptor_->listen(boost::asio::socket_base::max_listen_connections, ec);
if (ec)
LOG_ERR << "acceptor listen failed, ec = " << ec << ", msg = " << ec.message();
return;
iListener::~iListener()
delete acceptor_;
acceptor_ = NULL;
void iListener::run()
if (!acceptor_->is_open())
return;
do_accept();
NormalListener.h
class NormalListener:public iListener
public:
NormalListener(const std::string &addressStr, unsigned short port, boost::asio::io_context& ioc);
~NormalListener();
private:
void do_accept();
private:
;
NormalListener.cpp
NormalListener::NormalListener(const std::string &addressStr, unsigned short port, boost::asio::io_context& ioc):iListener(addressStr, port, ioc)
NormalListener::~NormalListener()
void NormalListener::do_accept()
auto sp = shared_from_this();
acceptor_->async_accept([&,sp](const boost::system::error_code& ec, boost::asio::ip::tcp::socket peer)
if (ec)
LOG_ERR << "acceptor async accept failed, ec = " << ec<<", msg = "<<ec.message();
return;
else
// Create the session and run it
std::make_shared<NormalSession>(std::move(peer))->run();
do_accept();
);
iSession.hpp
template<typename T>
class iSession : public std::enable_shared_from_this<iSession<T>>
public:
iSession()
ws_ = NULL;
strand_ = NULL;
buffer_ = new boost::beast::multi_buffer();
~iSession()
delete buffer_;
buffer_ = NULL;
delete strand_;
strand_ = NULL;
delete ws_;
ws_ = NULL;
public:
boost::beast::websocket::stream<T> *ws_ = NULL;
boost::asio::strand<boost::asio::io_context::executor_type> *strand_ = NULL;
boost::beast::multi_buffer *buffer_ = NULL;
public:
void virtual run() = 0;
protected:
void process()
private:
protected:
;
#endif //ESDK_MSP_ISESSION_HPP
NormalSession.h
class NormalSession : public iSession<boost::asio::ip::tcp::socket>
public:
NormalSession(boost::asio::ip::tcp::socket);
~NormalSession();
public:
void run();
protected:
;
NormalSession.cpp
NormalSession::NormalSession(boost::asio::ip::tcp::socket socket)
ws_ = new boost::beast::websocket::stream<boost::asio::ip::tcp::socket>(std::move(socket));
strand_ = new boost::asio::strand<boost::asio::io_context::executor_type>(ws_->get_executor());
NormalSession::~NormalSession()
void NormalSession::run()
auto sp = shared_from_this();
ws_->async_accept(boost::asio::bind_executor(*strand_, [&,sp](boost::system::error_code ec)
if (ec)
LOG_ERR << "acceptor async accept failed, ec = " << ec<<", msg = "<<ec.message();
return;
process();
));
【问题讨论】:
您发布的代码中的缓冲区在哪里?发布完整代码(或它的模拟) @Explorer_N 抱歉回复你太晚了,我还没有设置缓冲区..请看我现在编辑的代码。 在此之前,我认为您需要更正一下标题,因为我认为没有所谓的“Boost asio websocket”这种东西。我发现您正在使用 Boost.Beast。 @vainman 另外一件让我烦恼的事情是,为什么接受抛出“缓冲区溢出”,你认为接受需要缓冲区吗? @Explorer_N 我不知道,可能是 http 缓冲区?需要 chrome 的 CA 吗? 【参考方案1】:这在文档中有解释:
如果请求大小超过流内部的容量 缓冲区,将指示错误
websocket::buffer_overflow
。到 处理更大的请求,应用程序应该读取 HTTP 请求 直接使用http::async_read
,然后将请求传递给websocket::stream::accept
的适当过载或websocket::stream::async_accept
见: https://www.boost.org/doc/libs/1_70_0/libs/beast/doc/html/beast/ref/boost__beast__websocket__stream/async_accept/overload1.html
【讨论】:
感谢您的回答,但是当我尝试使用http::async_read时,总是出现error_code 995,IO线程已经退出。有什么样品或建议吗? 现在我使用 http::async_read 和 websocket::stream::async_accept ,它在 ws 中运行良好,但在 wss 中无法运行。 wss中如何使用? 是的,我终于找到了解决办法,谢谢你的提示以上是关于Boost Beast websocket 服务器异步接受失败,缓冲区溢出的主要内容,如果未能解决你的问题,请参考以下文章
Boost Beast websocket 服务器异步接受失败,缓冲区溢出
Boost :: Beast Websocket双向流(C ++)
如何正确写c++ boost beast websocket server
如何从另一个线程中断 websocket(使用 boost beast)?