Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 创建用于写入TCP套接字的消息_C++_Sockets_Tcp_Boost Asio - Fatal编程技术网

C++ 创建用于写入TCP套接字的消息

C++ 创建用于写入TCP套接字的消息,c++,sockets,tcp,boost-asio,C++,Sockets,Tcp,Boost Asio,我真的不知道该怎么回答这个问题,但我们开始吧 因此,让我们假设我正在使用boostlibs中的ASIO,使用TCP套接字连接到服务器并向其写入特定消息 该消息包含一些用户数据,如下所示:1字节(数据包ID)、4字节(整数)、以用户null结尾的字符串和6个零字节(由服务器保留但未使用) 使用ASIO的boost::ASIO::buffer函数组装这样的消息最方便的方法是什么 在这一点上我真的很困惑。非常感谢您的帮助。A.定义可以序列化的数据包结构 class ISerializable { pu

我真的不知道该怎么回答这个问题,但我们开始吧

因此,让我们假设我正在使用boostlibs中的ASIO,使用TCP套接字连接到服务器并向其写入特定消息

该消息包含一些用户数据,如下所示:1字节(数据包ID)、4字节(整数)、以用户null结尾的字符串和6个零字节(由服务器保留但未使用)

使用ASIO的boost::ASIO::buffer函数组装这样的消息最方便的方法是什么


在这一点上我真的很困惑。非常感谢您的帮助。

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());

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());

与使用
asio::buffer()
函数生成单个缓冲区不同,您可以将您的结构调整为-asio函数,以接受这样的概念。以这种方式发送一个模式,如fixed--null-terminated--null-terminated--fixed-fixed-fixed-etc,将非常方便。

您可以将您的结构调整为a,而不是使用
asio::buffer()
函数生成单个缓冲区,因为asio函数接受这样的概念。通过这种方式发送一个模式,例如fixed--null-terminated--null-terminated-fixed-fixed-etc,会很方便。

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 ) );
std::vector数据;
数据。推回(id);
数据。推回(i&0xff);
数据。推回((i>>8)和0xff);
数据。推回((i>>16)和0xff);
数据。推回((i>>24)和0xff);
const char*const str=s.c_str();
insert(data.end(),str,str+std::strlen(str));
用于(int pad=0;pad!=4;++pad)
数据。推回(0);
boost::asio::write(套接字,boost::asio::buffer(数据));
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 ) );
std::vector数据;
数据。推回(id);
数据。推回(i&0xff);
数据。推回((i>>8)和0xff);
数据。推回((i>>16)和0xff);
数据。推回((i>>24)和0xff);
const char*const str=s.c_str();
insert(data.end(),str,str+std::strlen(str));
用于(int pad=0;pad!=4;++pad)
数据。推回(0);
boost::asio::write(套接字,boost::asio::buffer(数据));

您的消息是字符串还是结构?这是我实际上无法决定的。我尝试过使用字符串,但我不确定用必要的字节数据填充字符串的最合适方式是什么,尤其是如果它是最好的选择,假设ASIO引用声明它可能与std::vector或std::string同样有效。我想用一个struct来做这个,但我不完全确定如何正确地做。你的消息是字符串还是结构?这是我实际上无法决定的。我尝试过使用字符串,但我不确定用必要的字节数据填充字符串的最合适方式是什么,尤其是如果它是最好的选择,假设ASIO引用声明它可能与std::vector或std::string同样有效。我想使用一个Stand,但是我不太确定如何正确地处理它。<代码>和int(0)< /C>是C++ 11的东西,或者我从来没有在C++中知道过这个问题?我不会使用一个二进制协议的流。流缓冲区在这里更合适。而且虚拟函数没有任何用处,至少没有,除非有某种多态数据结构需要序列化;使此实现高度依赖于实现。@ViteFalcon仅通过写入整数表示的前4个字节来写入整数有两个问题:第一,int不必是4个字节。这甚至可以从同一编译器的一个版本更改为下一个版本。如果幸运的话,大小变成了8个字节,那么就写了int的“右”半部分。我建议至少使用“sizeof int”。另一个问题是int在内存中的表示(小端、大端等)。在同一个平台上,这可能是相同的,但是我们在讨论网络时,在阅读方面可能会有所不同。@ TrStRoButZKI或使用<代码> INT32×T< <代码>等是<代码>和int(0)< /C> C++ 11的东西,或者我从来没有在C++中知道过这一点?我不会使用流作为二进制协议。流缓冲区在这里更合适。而且虚拟函数没有任何用处,至少没有,除非有某种多态数据结构需要序列化;使此实现高度依赖于实现。@ViteFalcon仅通过写入整数表示的前4个字节来写入整数有两个问题:第一,int不必是4个字节。这甚至可以从同一编译器的一个版本更改为下一个版本。如果幸运的话,大小变成了8个字节,那么就写了int的“右”半部分。我建议至少使用“sizeof int”。另一个问题是int在内存中的表示(小端、大端等)。在同一平台上,这可能是相同的,但在我们谈论网络时,在阅读方面可能会有所不同。@TorstenRobitzki或使用
int32\t
等。难道没有一种方法可以以更紧凑的方式编写非字符类型吗?@Insmniaarray这取决于您的要求。但是,将二进制协议定义到最低位似乎是一项工作量不大的工作。您有多少不同的基本数据类型?一个布尔,一个i