簡體   English   中英

Boost ASIO - 無法從正文讀取數據包標頭

[英]Boost ASIO - Unable to read packet header from body

我使用 Boost ASIO,我想將標題與正文消息分開。

這是我的操作碼枚舉:

enum ServerOpcode : uint16_t{
    SMSG_AUTH_CONNECTION_RESPONSE                    = 0x001,
    SMSG_LOGIN_REQUEST_RESPONSE                      = 0x002,
    SMSG_LOGIN_REQUEST_RESPONSE_TEST                 = 0x1A6,
};

這是我發送消息的方式:

boost::asio::io_context io_context;
std::vector<tcp::socket> sockets;
for (int i = 0; i < connectionsNumber; ++i) {
    try
    {
        sockets.emplace_back(io_context);
        tcp::socket& s{sockets.back()};
        tcp::resolver resolver(io_context);
        boost::asio::connect(s, resolver.resolve( defaultIP,config.GetConfigValue("AuthServerPort", defaultPort)));

        enum { body_length = 1024 };
        enum { header_length = 8 };
        enum { max_length = body_length +  header_length};
        char header_[header_length];
        char body_[body_length];
        char data_[header_length + body_length];

        ServerOpcode opc;
        opc = ServerOpcode::SMSG_LOGIN_REQUEST_RESPONSE_TEST;
        std::string message = "I am testing here!!!";


        snprintf(header_,header_length,"%x",opc);
        strcpy(body_, message.c_str());
        sprintf(data_, "%s %s", header_, body_);

        size_t request_length = sizeof(data_)/sizeof(*data_);
        std::cout << "Header: " << header_ << std::endl;
        std::cout << "body: " << body_ << std::endl;
        std::cout << "whole message is: " << data_ << std::endl;
        std::cout << "size: " << request_length << std::endl;
        std::cout << "max size: " << max_length << std::endl;

        boost::asio::write(s, boost::asio::buffer(data_, request_length));

    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }

}

這是我在服務器上閱讀它的方式:

void Vibranium::Client::read_header() {
    auto self(shared_from_this());
    boost::asio::async_read(socket,
    boost::asio::buffer(_packet.data_, _packet.header_length),
    [this, self](boost::system::error_code ec, std::size_t /*length*/)
    {
        if (!ec)
        {
            std::cout << "Header: " << std::endl;
            std::cout.write(_packet.data_, _packet.header_length);
            std::cout << "\n";
            //read_body();
        }
        else
        {
            std::cerr << "Invalid header sent!" << std::endl;
        }
    });
}

Packet.h

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "string"
#include "Protocol/ServerOpcode.h"

class Packet {
public:
    Packet() : body_length_(0)
    {
    }
    enum { max_body_length = 1024 };
    enum { header_length = 8 };
    char header_[header_length];
    char body_[max_body_length];
    char data_[header_length + max_body_length];
    char * body();
    void PreparePacket(ServerOpcode serverOpcode, std::string message);
    std::size_t body_length() const;
private:
    std::size_t body_length_;
};


#endif //VIBRANIUM_CORE_PACKET_H

但是我看到輸出為:

New Connection (ID: 4)
Header: 
1a6 I am

那是不正確的! 為什么Header:顯示1a6 I am 我的錯誤在哪里? 我希望它只是1a6 我該如何解決?

在閱讀后在這一行中:

std::cout.write(_packet.data_, _packet.header_length);

header_length 是 8 = '1a6 I am' 的長度

如果您只想擁有 '1a6',您的標題長度應該是 3(而不是 8)。

這一行: snprintf(header_,header_length,"%x",opc); 如果你要打印它,它的末尾應該有一個換行符。 如果是這種情況,您應該將緩沖區擴展 1 以允許換行。 或者更好的是,打印預期的字符並在需要打印時指定特定長度(就像您在服務器上所做的那樣):

            std::cout << "Header: " << std::endl;
            std::cout.write(_packet.data_, _packet.header_length);
            std::cout << "\n";

現在編寫代碼時,輸​​出繼續(在連續內存中),直到遇到下一個換行符。

此外,我建議使用vector<uint_8>而不是數組,因為它們允許邊界檢查並允許Packet類型的默認可移動/可復制語義。 您也可以考慮使用boost::asio::buffer類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM