组合多种数据类型以配制数据包

时间:2014-03-24 07:43:43

标签: c++ sockets templates c++11 packet

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

你会构造一个新的数据包,这个数据包会有'数据变量',不知道应该是什么类型的变量,网络库允许数据作为'const void *'发送

DataPacket *Packet = new DataPacket();

将数据添加到数据包中,这会传递您指定类型的值,并将其“附加”到“数据变量”的末尾

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

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

Packet.Send();

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

DataPacket *Packet = new DataPacket(Data);

按照您编写的相同顺序读出数据,每次调用GetData时,从头到尾移动“数据变量”多一点

int Var1 = Packet.GetData<int>();
bool Var2 = Packet.GetData<bool>();
const char* Var3 = Packet.GetData<const char*>();

我很困惑的是这个'数据变量'应该是什么类型的变量,如何从这个'数据变量'构造一个相同的数据包,以及如何将变量放入和取出'数据变量'像函数一样设置。

2 个答案:

答案 0 :(得分:2)

编辑: 我似乎误解了你的问题。如果要将数据传输到远程计算机,即通过网络或其他东西,您需要一个序列化库,如Boost.Serialization:http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html。将类型(尤其是非平凡类型)转换为字节流然后再将它们转换回来并非易事。我会选择加强。

我的原始答案仅适用于在流程内部发送数据但不在流程外部发送数据:

如果您不想使用boost.any或boost.variant,您可以使用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

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

答案 1 :(得分:0)

在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"));
}