[英]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.