在C++中使用boost::Beast的Websocket客户端--在写操作时抛出错误。

问题描述 投票:1回答:1

下面是一段代码,我正在努力让它成功。我使用的是git hub的参考代码。https:/www.boost.orgdoclibs1_70_0libsbeastdochtmlbeastquick_startwebsocket_client.html.问题是当我在同一个函数中调用连接方法并进行写操作时,它可以工作,但如果我把它放在不同的函数中,它就不会工作。

我对 boost 和 shared_pointer 是个新手,如果我说的不对,请原谅。

    // Sends a WebSocket message and prints the response
    class CWebSocket_Sync : public std::enable_shared_from_this<CWebSocket_Sync>
    {
        tcp::resolver resolver_;
        websocket::stream<tcp::socket> ws_;
        boost::beast::multi_buffer buffer_;
        std::string host_;
        std::string text_;

    public:
        // Resolver and socket require an io_context
        explicit
            CWebSocket_Sync(boost::asio::io_context& ioc)
            : resolver_(ioc)
            , ws_(ioc)
        {
        }

        void 
            connect(
                char const* host,
                char const* port,
                char const* text)
        {
            // Save these for later
            host_ = host;
            text_ = text;

            // Look up the domain name
            auto const results = resolver_.resolve(host, port);

            // Make the connection on the IP address we get from a lookup
            auto ep = net::connect(ws_.next_layer(), results);

            // Update the host_ string. This will provide the value of the
            // Host HTTP header during the WebSocket handshake.
            // See https://tools.ietf.org/html/rfc7230#section-5.4
            host_ += ':' + std::to_string(ep.port());

            // Perform the websocket handshake
            ws_.handshake(host_, "/");

            //ws_.write(net::buffer(std::string(text)));
            //// This buffer will hold the incoming message
            //beast::flat_buffer buffer;

            //// Read a message into our buffer
            //ws_.read(buffer);


        }

        void ServerCommand(char const* text)
        {
            ws_.write(net::buffer(std::string(text)));   // <-- this line throw memory error 

            // This buffer will hold the incoming message
            beast::flat_buffer buffer;

            // Read a message into our buffer
            ws_.read(buffer);


            // The make_printable() function helps print a ConstBufferSequence
            std::cout << beast::make_printable(buffer.data()) << std::endl;
        }

        void CloseConnection()
        {
            // Close the WebSocket connection
            ws_.close(websocket::close_code::normal);
        }

    };
int main(int argc, char** argv)
{
    auto const host = "127.0.0.1";
    auto const port = "7011";
    auto const loginCmd = "login"
    boost::asio::io_context ioc;

    std::make_shared<CWebSocket_Sync>(ioc)->connect(host, port, loginCmd);

    std::make_shared<CWebSocket_Sync>(ioc)->ServerCommand(loginCmd);

    std::make_shared<CWebSocket_Sync>(ioc)->CloseConnection();

    return EXIT_SUCCESS;
}
c++ websocket boost-asio shared-ptr boost-beast
1个回答
0
投票
std::make_shared<CWebSocket_Sync>(ioc)->connect(host, port);
std::make_shared<CWebSocket_Sync>(ioc)->ServerCommand(loginCmd);
std::make_shared<CWebSocket_Sync>(ioc)->CloseConnection();

每一行都会创建一个新的客户端 (make_shared<CWebSocket_Sync>),并在其上运行单步。你可能想要的。

auto client = std::make_shared<CWebSocket_Sync>(ioc);
client->connect(host, port);
client->ServerCommand(loginCmd);
client->CloseConnection();

的确是这样的:

#include <boost/beast.hpp>
#include <boost/beast/websocket.hpp>
#include <memory>
#include <iostream>

namespace net       = boost::asio;
namespace beast     = boost::beast;
namespace websocket = beast::websocket;
using net::ip::tcp;

// Sends a WebSocket message and prints the response
class CWebSocket_Sync : public std::enable_shared_from_this<CWebSocket_Sync> {
    tcp::resolver resolver_;
    websocket::stream<tcp::socket> ws_;
    boost::beast::multi_buffer buffer_;
    std::string host_;

public:
    // Resolver and socket require an io_context
    explicit CWebSocket_Sync(boost::asio::io_context& ioc)
        : resolver_(ioc), ws_(ioc) { }

    void connect(char const* host, char const* port) {
        // Save these for later
        host_ = host;

        // Look up the domain name
        auto const results = resolver_.resolve(host, port);

        // Make the connection on the IP address we get from a lookup
        auto ep = net::connect(ws_.next_layer(), results);

        // Update the host_ string. This will provide the value of the
        // Host HTTP header during the WebSocket handshake.
        // See https://tools.ietf.org/html/rfc7230#section-5.4
        host_ += ':' + std::to_string(ep.port());

        // Perform the websocket handshake
        ws_.handshake(host_, "/");
    }

    void ServerCommand(char const* text) {
        ws_.write(net::buffer(std::string(text)));   // <-- this line throw memory error 

        beast::flat_buffer buffer;
        ws_.read(buffer);

        std::cout << beast::make_printable(buffer.data()) << std::endl;
    }

    void CloseConnection() {
        ws_.close(websocket::close_code::normal);
    }
};

int main() {
    auto const host = "127.0.0.1";
    auto const port = "7011";
    auto const loginCmd = "login";
    boost::asio::io_context ioc;

    auto client = std::make_shared<CWebSocket_Sync>(ioc);
    client->connect(host, port);
    client->ServerCommand(loginCmd);
    client->CloseConnection();
}

SIMPLIFY

然而,既然没有什么使用共享寿命,而且你也没有在任何地方使用异步调用,为什么不干脆。

Live On Coliru

class CWebSocket_Sync {

和后来。

    CWebSocket_Sync client(ioc);
    client.connect(host, port);
    client.ServerCommand(loginCmd);
    client.CloseConnection();
© www.soinside.com 2019 - 2024. All rights reserved.