C++ 结构的序列化
假设我有一个结构,我想通过网络将其成员值发送到另一个使用winsock 2的系统。我用C++语言。 如何将其转换为char*,记住在发送之前必须序列化结构,以及如何在另一端将char*反序列化为struct?我发现boost序列化是对类似问题的一个建议,但有人能用一个小代码段来说明序列化和反序列化吗C++ 结构的序列化,c++,serialization,deserialization,winsock2,C++,Serialization,Deserialization,Winsock2,假设我有一个结构,我想通过网络将其成员值发送到另一个使用winsock 2的系统。我用C++语言。 如何将其转换为char*,记住在发送之前必须序列化结构,以及如何在另一端将char*反序列化为struct?我发现boost序列化是对类似问题的一个建议,但有人能用一个小代码段来说明序列化和反序列化吗 这个问题可能看起来很基本,但相关帖子的其他答案没有多大帮助。如果你的结构是POD,你可以使用memcpy: ::memcpy(数据和你的结构,sizeof(你的结构)) 接待时也一样: ::memc
这个问题可能看起来很基本,但相关帖子的其他答案没有多大帮助。如果你的结构是
POD
,你可以使用memcpy
:
::memcpy(数据和你的结构,sizeof(你的结构))代码>
接待时也一样:
::memcpy(&your_struct,data,sizeof(your struct))代码>
其中,data
是一个char*
。别忘了你必须分配它,确保它足够大,并在最后删除它。好的,我将从boost网站上获取,因为我不明白你不能从中理解的内容。
我添加了一些注释和更改,以了解如何通过网络进行传输。网络代码本身不在这里。对于这一点,你可以看看
intmain(){
//创建并打开用于输出的角色存档
//我们在这里只使用std::strinstream
std::stringstreamofs;
//创建类实例
常数gps_位置g(35,59,24.567f);
//将数据保存到存档
{
boost::archive::text\u oarchive oa(ofs);
//将类实例写入存档
oa>newg;
//调用析构函数时归档和流关闭
}
返回0;
}
你可以这样做
struct MyStruct {
int data;
char* someNullTerminatedName; // Assuming not larger than 1023 chars
std::ostream& serialize(std::ostream& os) const {
char null = '\0';
os.write((char*)&data, sizeof(data));
os.write(someNullTerminatedName, strlen(someNullTerminatedName));
os.write(&null, 1);
return os;
}
std::istream& deserialize(std::istream& is) {
char buffer[1024];
int i = 0;
is.read((char*)&data, sizeof(data));
do { buffer[i] = is.get(); ++i; } while(buffer[i] != '\0');
if (someNullTerminatedName != NULL) free(someNullTerminatedName);
someNullTerminatedName = (char*)malloc(i);
for (i = 0; buffer[i] != '\0'; ++i) {
someNullTerminatedName[i] = buffer[i];
}
return is;
}
};
由您来处理int
s和诸如此类的文件的长度和大小差异
例如:
MyStruct foo, bar;
std::stringstream stream;
foo.serialize(stream);
// ... Now stream.str().c_str() contains a char* buffer representation of foo.
// For example it might contain [ 1f 3a 4d 10 h e l l o w o r l d \0 ]
bar.deserialize(stream);
// ... Now bar is a copy, via a serial stream of data, of foo.
如果你有一个通过C++ iOFFISH公开它的接口的socket库,那么你甚至不需要StrugSuff.[/P>< p>你也可以从谷歌上查看它是一个平台/语言无关的库,用于在主机之间发送数据。
然而,这种范式已经转向先编写协议,然后将数据结构装配到协议中。不过,这样做的好处是它强制您的软件体系结构与简单的数据类型很好地匹配。下面的示例显示了将struct
序列化为char
数组并将其反序列化的最简单方法
#include <iostream>
#include <cstring>
#define BUFSIZE 512
#define PACKETSIZE sizeof(MSG)
using namespace std;
typedef struct MSG
{
int type;
int priority;
int sender;
char message[BUFSIZE];
}MSG;
void serialize(MSG* msgPacket, char *data);
void deserialize(char *data, MSG* msgPacket);
void printMsg(MSG* msgPacket);
int main()
{
MSG* newMsg = new MSG;
newMsg->type = 1;
newMsg->priority = 9;
newMsg->sender = 2;
strcpy(newMsg->message, "hello from server\0");
printMsg(newMsg);
char data[PACKETSIZE];
serialize(newMsg, data);
MSG* temp = new MSG;
deserialize(data, temp);
printMsg(temp);
return 0;
}
void serialize(MSG* msgPacket, char *data)
{
int *q = (int*)data;
*q = msgPacket->type; q++;
*q = msgPacket->priority; q++;
*q = msgPacket->sender; q++;
char *p = (char*)q;
int i = 0;
while (i < BUFSIZE)
{
*p = msgPacket->message[i];
p++;
i++;
}
}
void deserialize(char *data, MSG* msgPacket)
{
int *q = (int*)data;
msgPacket->type = *q; q++;
msgPacket->priority = *q; q++;
msgPacket->sender = *q; q++;
char *p = (char*)q;
int i = 0;
while (i < BUFSIZE)
{
msgPacket->message[i] = *p;
p++;
i++;
}
}
void printMsg(MSG* msgPacket)
{
cout << msgPacket->type << endl;
cout << msgPacket->priority << endl;
cout << msgPacket->sender << endl;
cout << msgPacket->message << endl;
}
#包括
#包括
#定义BUFSIZE 512
#定义PACKETSIZE sizeof(MSG)
使用名称空间std;
类型定义结构消息
{
int型;
int优先级;
int发送器;
字符消息[BUFSIZE];
}味精;
void序列化(MSG*msgPacket,char*data);
void反序列化(char*data,MSG*msgPacket);
void printMsg(MSG*msgPacket);
int main()
{
MSG*newMsg=newMsg;
newMsg->type=1;
newMsg->priority=9;
newMsg->sender=2;
strcpy(newMsg->message,“hello from server\0”);
printMsg(newMsg);
字符数据[PACKETSIZE];
序列化(newMsg,数据);
味精*温度=新味精;
反序列化(数据、温度);
printMsg(temp);
返回0;
}
void序列化(MSG*msgPacket,char*data)
{
int*q=(int*)数据;
*q=msgPacket->type;q++;
*q=msgPacket->priority;q++;
*q=msgPacket->sender;q++;
char*p=(char*)q;
int i=0;
而(imessage[i];
p++;
i++;
}
}
void反序列化(char*data,MSG*msgPacket)
{
int*q=(int*)数据;
msgPacket->type=*q;q++;
msgPacket->priority=*q;q++;
msgPacket->sender=*q;q++;
char*p=(char*)q;
int i=0;
而(imessage[i]=*p;
p++;
i++;
}
}
void printMsg(MSG*msgPacket)
{
不能在Boost网站上键入什么?在发送端:结构示例{int a;float b;double c;};示例ex;ex.a=1;ex.b=1.02;ex.c=1.040;::memcpy(Buffer,&ex,sizeof(示例));retval=send(conn_socket,Buffer,sizeof(Buffer),0);在接收端:示例ex;retval=recvfrom(msgsock,Buffer,sizeof(Buffer),0,(struct sockaddr*)&from,&fromlen);::memcpy(&ex,Buffer,sizeof(示例));printf(“%f”,ex.c);输出:-62774385622041925000000000000000000000000000000。这是为什么?在复制结构时需要非常小心,因为不同的体系结构和不同的编译器将以不同的方式应用填充和终止。我在两个系统上都使用Visual studio 2005和XP。但是为什么会有这种差异?缓冲区来自哪里m?你确定它比你的结构大吗?是的..我已经为我的缓冲区malloc了60个字节,而结构很容易小于60..简单序列化的一个很好的例子你的代码有两个内存泄漏。实际上根本不需要使用新的
。这里有进一步可能的改进:1.使MSG成为E反序列化函数而不是输出参数2,而不是<代码> MSG {…} MSG;< /COD>使用<代码>结构MSG{{}};< /C> >,在C++ 3中是相同的。使用<代码> STD::String < /C> >或“代码> STD::vector < /COD>保存序列化数据(并处理该<代码>定义包大小< /COD>)并将其用作serialize
函数的返回值,而不是输出参数(或者如果您坚持将参数更改为char(&data)[PACKETSIZE]
)。这假设发送方和接收方都知道结构的成员。如果结构的每个成员的详细信息也被嵌入和发送,接收方可以使用它来构建适当的指针。一端简单的更改而另一端不知道会导致很多错误。这是一个很好的简单实现,没错。但是以下是这种实现肯定不起作用的情况:1)如果发送方和接收方没有相同的结构实现(如@AlphaGok)
#include <iostream>
#include <cstring>
#define BUFSIZE 512
#define PACKETSIZE sizeof(MSG)
using namespace std;
typedef struct MSG
{
int type;
int priority;
int sender;
char message[BUFSIZE];
}MSG;
void serialize(MSG* msgPacket, char *data);
void deserialize(char *data, MSG* msgPacket);
void printMsg(MSG* msgPacket);
int main()
{
MSG* newMsg = new MSG;
newMsg->type = 1;
newMsg->priority = 9;
newMsg->sender = 2;
strcpy(newMsg->message, "hello from server\0");
printMsg(newMsg);
char data[PACKETSIZE];
serialize(newMsg, data);
MSG* temp = new MSG;
deserialize(data, temp);
printMsg(temp);
return 0;
}
void serialize(MSG* msgPacket, char *data)
{
int *q = (int*)data;
*q = msgPacket->type; q++;
*q = msgPacket->priority; q++;
*q = msgPacket->sender; q++;
char *p = (char*)q;
int i = 0;
while (i < BUFSIZE)
{
*p = msgPacket->message[i];
p++;
i++;
}
}
void deserialize(char *data, MSG* msgPacket)
{
int *q = (int*)data;
msgPacket->type = *q; q++;
msgPacket->priority = *q; q++;
msgPacket->sender = *q; q++;
char *p = (char*)q;
int i = 0;
while (i < BUFSIZE)
{
msgPacket->message[i] = *p;
p++;
i++;
}
}
void printMsg(MSG* msgPacket)
{
cout << msgPacket->type << endl;
cout << msgPacket->priority << endl;
cout << msgPacket->sender << endl;
cout << msgPacket->message << endl;
}