我真的不知道如何提出这个问题,但我们开始吧。
所以让我们假设我正在使用 Boost 库中的 ASIO 来使用 TCP 套接字连接到服务器并向其写入特定消息。
该消息包含一些用户数据,如下所示:1 个字节(数据包 ID)、4 个字节(整数)、用户以 null 结尾的字符串和 6 个零字节(由服务器保留但未使用)。
组装这样的消息以与 ASIO 的 boost::asio::buffer 函数一起使用的最方便的方法是什么?
在这一点上我真的很困惑。非常感谢帮助。
我真的不知道如何提出这个问题,但我们开始吧。
所以让我们假设我正在使用 Boost 库中的 ASIO 来使用 TCP 套接字连接到服务器并向其写入特定消息。
该消息包含一些用户数据,如下所示:1 个字节(数据包 ID)、4 个字节(整数)、用户以 null 结尾的字符串和 6 个零字节(由服务器保留但未使用)。
组装这样的消息以与 ASIO 的 boost::asio::buffer 函数一起使用的最方便的方法是什么?
在这一点上我真的很困惑。非常感谢帮助。
asio::buffer()
您可以将结构调整为缓冲区序列,而不是使用函数制作单个缓冲区- asio 函数接受这样的概念。以这种方式发送固定--null-terminated--null-terminated-fixed-fixed-etc 之类的模式会很方便...
A. 定义可以序列化的数据包结构。
class ISerializable
{
public:
virtual ~ISerializable(){}
virtual void serialize(std::ostream& stream) = 0;
};
class LoginPacket : public ISerializable
{
public:
// Constructor and access functions
virtual void serialize(std::ostream& stream)
{
stream.write((const char*)&packetId, 1);
stream.write((const char*)&accountId, 4);
stream.write(username.c_str(), username.size() + 1);
// Write the unused 6-bytes of zero
int zero(0);
stream.write((const char*)&zero, 4);
stream.write((const char*)&zero, 2);
}
private:
unsigned char packetId;
unsigned int32_t accountId;
std::string username;
};
B. 现在,要使用这个数据包类,请执行以下操作:
LoginPacket packet;
// Fill details for the packet
std::stringstream data;
packet.serialize(data);
// Send the data to the network
yourSocket.send(data.str().c_str(), data.str().size());
boost::asio::buffer() 函数将其他类型的缓冲区调整或转换为 asio 使用的缓冲区。
您应该使用某种应用程序缓冲区,填充该缓冲区,然后将缓冲区传递给 asio 以写入线路。例如:
std::vector< char > data;
data.push_back( id );
data.push_back( i & 0xff );
data.push_back( ( i >> 8 ) & 0xff );
data.push_back( ( i >> 16 ) & 0xff );
data.push_back( ( i >> 24 ) & 0xff );
const char* const str = s.c_str();
data.insert( data.end(), str, str + std::strlen( str ) );
for ( int pad = 0; pad != 4; ++pad )
data.push_back( 0 );
boost::asio::write( socket, boost::asio::buffer( data ) );