首页 > 解决方案 > 字符串流与直接字符串

问题描述

我正在尝试将 STOMP 帧发送到服务器。我首先尝试使用 std::string 直接创建消息,但服务器一直抱怨我做错了。但是,当我使用 stringstream 创建消息时,它可以工作。任何人都可以发现我的错误吗?代码如图所示。它抱怨它在消息末尾找不到终止符 \0 (parsingmissingnullinbody)。

bool CheckResponse(const std::string& response)
{
// We do not parse the whole message. We only check that it contains some
// expected items.
bool ok {true};
ok &= response.find("ERROR") != std::string::npos;
ok &= response.find("ValidationInvalidAuth") != std::string::npos;
std::cout << response << "\n";
return ok;
}

BOOST_AUTO_TEST_CASE(connect_to_network_events){
    // Always start with an I/O context object.
    boost::asio::io_context ioc {};

    // Create also a tls context
    boost::asio::ssl::context ctx{boost::asio::ssl::context::tlsv12_client};
    // Connection targets
    const std::string url {"ltnm.learncppthroughprojects.com"};
    const std::string port {"443"};
    const std::string endpoint {"/network-events"};

    // The class under test
    WebSocketClient client {url, endpoint, port, ioc, ctx};

    // MY ATTEMPT AT CREATING MESSAGE DIRECTLY, THIS FAILED
    // const std::string message {"STOMP\naccept-version:1.2\nhost:transportforlondon.com\nlogin:fake_username\npasscode:fake_password\n\n\0"};

    // THE FOLLOWING SUCCEEDED INSTEAD
    const std::string username {"fake_username"};
    const std::string password {"fake_password"};
    std::stringstream ss {};
    ss << "STOMP" << std::endl
       << "accept-version:1.2" << std::endl
       << "host:transportforlondon.com" << std::endl
       << "login:" << username << std::endl
       << "passcode:" << password << std::endl
       << std::endl // Headers need to be followed by a blank line.
       << '\0'; // The body (even if absent) must be followed by a NULL octet.
    const std::string message {ss.str()};

    std::string response;
    // We use these flags to check that the connection, send, receive functions
    // work as expected.
    bool connected {false};
    bool messageSent {false};
    bool messageReceived {false};
    bool messageMatches {false};
    bool disconnected {false};

    // Our own callbacks
    auto onSend {[&messageSent](auto ec) {
        messageSent = !ec;
    }};
    auto onConnect {[&client, &connected, &onSend, &message](auto ec) {
        connected = !ec;
        if (!ec) {
            client.Send(message, onSend);
        }
    }};
    auto onClose {[&disconnected](auto ec) {
        disconnected = !ec;
    }};
    auto onReceive {[&client,
                      &onClose,
                      &messageReceived,
                      &messageMatches,
                      &message,
                      &response](auto ec, auto received) {
        messageReceived = !ec;
        response = received;
        client.Close(onClose);
    }};

    // We must call io_context::run for asynchronous callbacks to run.
    client.Connect(onConnect, onReceive);
    ioc.run();

    BOOST_CHECK(CheckResponse(response));
}

标签: c++stomp

解决方案


创建std::stringfromconst char *将忽略终止 NULL 字符。您可以使用char[]构造函数,但我认为它不适合您的用例。

例子:

// Example program
#include <iostream>
#include <string>

int main()
{
    std::string message1 {"STOMP\naccept-version:1.2\nhost:transportforlondon.com\nlogin:fake_username\npasscode:fake_password\n\n\0"};
    std::cout << message1.length() << std::endl;
    
    std::string message2 {"STOMP\naccept-version:1.2\nhost:transportforlondon.com\nlogin:fake_username\npasscode:fake_password\n\n"};
    std::cout << message2.length() << std::endl;
    
    message2.push_back('\0');
    std::cout << message2.length() << std::endl;
}

输出:

97
97
98

因此,您只需要创建没有终止 NULL 字符的消息,然后附加\0.

更新:如果你在C++14你可能想要使用字符串文字:

using namespace std::string_literals;

// ... 

std::string message = "STOMP\naccept-version:1.2\nhost:transportforlondon.com\nlogin:fake_username\npasscode:fake_password\n\n\0"s;

注意s字符串末尾的 。


推荐阅读