http - Boost beast websocket 服务器异步接受失败,缓冲区溢出

标签 http websocket boost-asio boost-beast

我通过 boost asio websocket 编写了一个 websocket 服务器。 当我尝试将它与 chrome 连接时,它总是说连接失败。 日志显示缓冲区溢出。 尤其是在我打开很多网站之后。

[2019-06-21 16:40:45.071345]-[0x00003130]-[error]:[NormalSession.cpp:75] acceptor async accept failed, ec = beast.http:7, msg = buffer overflow

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 endpoint{address, 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:

};

正常 session .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();
    }));

}

最佳答案

这在文档中有解释:

If the request size exceeds the capacity of the stream's internal buffer, the error websocket::buffer_overflow will be indicated. To handle larger requests, an application should read the HTTP request directly using http::async_read and then pass the request to the appropriate overload of websocket::stream::accept or 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 - Boost beast websocket 服务器异步接受失败,缓冲区溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56700383/

相关文章:

javascript - 在 node.js 中设置下载响应的文件名

facebook - 应用程序名称在自动收报机上显示不正确

websocket - 在客户端等待来自websocket的响应

boost - 如何使用 boost.asio 创建一个简单的服务器/客户端应用程序?

javascript - 等待 RootCtrl Angular $http 中的 promise

python - 检查 url 是否与网站相关

c++ - boost::asio async_read 保证读取所有字节

c++ - 如何将 boost asio tcp 套接字传递给线程以向客户端或服务器发送心跳

javascript - 如何在单个 vuejs 项目中连接多个套接字?

c - libwebsockets for C,我可以将 websocket 文件描述符与 select() 一起使用吗?