将多种数据类型组合成一个报文

Combine Multiple Data Types To Formulate A packet

本文关键字:一个 报文 数据类型 组合      更新时间:2023-10-16

我正在尝试创建一个类,它将多种类型的变量组合成一个变量,该变量可用于发送到远程机器并从该数据重建类。

你将构建一个新的数据包,该数据包将具有'data变量',不确定这应该是什么类型的变量,网络库允许数据以'const void *'发送

DataPacket *Packet = new DataPacket();

将数据添加到数据包中,这将传递您指定的类型的值,并将其"追加"到'data变量'的末尾

Packet.AddData<int>(45);
Packet.AddData<bool>(true);
Packet.AddData<const char*>("Test");

发送数据包,这实际上会通过网络库将'data变量'发送到远程机器

Packet.Send();

在接收机器上构造一个数据包,将我们发送的'数据变量'传递给它,这将构造从发送机器发送的数据包的副本

DataPacket *Packet = new DataPacket(Data);

每次调用GetData

时,按照您写入数据的顺序从开始到结束移动'data变量'
int Var1 = Packet.GetData<int>();
bool Var2 = Packet.GetData<bool>();
const char* Var3 = Packet.GetData<const char*>();

我感到困惑的是这个"数据变量"应该是什么类型的变量,如何从这个"数据变量"构建一个相同的数据包,以及如何将变量放入和取出"数据变量"与get设置类似的函数。

编辑:我似乎误解了你的问题。如果您想要将数据传输到远程机器,例如通过网络或其他方式,则需要像Boost这样的序列化库。序列化:http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html。将类型(尤其是重要类型)转换为字节流,然后再将其转换回来并不是一件容易的事情。我会选boost。

我的原始答案,它只适用于在进程内发送数据,而不是在进程外:

如果你不想使用boost。任何或提升。您可以使用来自Sean Parent的优秀的非侵入式多态性模式来创建自己的变体:

class PacketData{
    struct Context {
        virtual ~Context() = default;
    };
    template<typename T>
    struct Instance : Context {
        Instance(T&& t):data_{std::move(t)}{
        }
        T data_;
    };
    std::unique_ptr<Context> self_;
    public:
    template<typename T>
    PacketData(T in):self_{new Instance<T>{std::move(in)}}{}
    //move is easy, copy is harder ;)
    template<typename T>
    bool isA(){
        return dynamic_cast<Instance<T>*>(self_.get()) != nullptr;
    }
    template<typename T>
    T& asA(){
        if(!isA<T>()){
            throw std::runtime_error("bad cast or something");
        }
        return dynamic_cast<Instance<T>*>(self_.get())->data_;
    }
};

创建了这个变体类之后,剩下的应该很容易了:

using Packet = std::vector<PacketData>;

Packet packet;
packet.push_back(4);
packet.push_back(4.4f);
packet.push_back(std::string{"test"});
int i = packet[0].asA<int>();
float f = packet[1].asA<float>();
std::string s = packet[2].asA<std::string>();

下面是一个实例:http://ideone.com/U7rmOL

如果您想要速度,您可以通过在packketdata类中放置一个堆栈分配器来绕过堆分配,该分配器足够大以容纳通常的数据大小。见http://home.roadrunner.com/~ hinnant/stack_alloc.html

在GoingNative/channel9中有一种技术(我似乎已经找不到了)。它是这样的:

#include <vector>
class Packet
{
    class Generic
    {};
    template <typename C>
    class Content : public Generic
    {
        C content;
    public:
        Content() : Generic(), content() {}
        Content(const C& c) : Generic(), content(c) {}
        ~Content() {}
        C& getContent() const { return content; }
    };
    std::vector<Generic> packet_content;
public:
    Packet() : packet_content() {}
    template <typename X>
    void add(X x) { packet_content.push_back(Content<X>(x)); }
};

int main()
{
    Packet packet;
    packet.add(5);
    packet.add(std::string("hello"));
    packet.add(55);
    packet.add(false);
    packet.add(std::string("world"));
}