将多种数据类型组合成一个报文
Combine Multiple Data Types To Formulate A packet
我正在尝试创建一个类,它将多种类型的变量组合成一个变量,该变量可用于发送到远程机器并从该数据重建类。
你将构建一个新的数据包,该数据包将具有'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"));
}
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 运行同一解决方案的另一个项目的项目
- 挂起和取消挂起一个文件DLL
- 用C++中的一个变量定义一个常量
- 函数向量_指针有不同的原型,我可以构建一个吗
- 在c++中用vector填充一个简单的动态数组
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 预处理器:插入结构名称中的前一个行号
- 我在c++代码中生成了一个运行时#3异常
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 从链接列表c++中删除一个项目
- 告诉一个 const char 数组,除了编译时 C 样式的字符串外,它不以 '