JJ *_*Liu 11 c++ sockets serialization struct
说我有一个结构:
struct person
{
char name[10];
int age;
};
struct car
{
int locationX;
int locationY;
};
struct company
{
vector<person> employees;
vector<car> cars;
};
Run Code Online (Sandbox Code Playgroud)
例如,我想要send/recv整个company使用套接字(UDP).所以,发送和recv一次.
我怎样才能做到这一点?你能给我一些代码吗?如何发送所有内容并阅读所有内容.
谢谢!
Omn*_*ous 18
您的问题的措辞表明您正在寻找的是:
company foo;
send(sockfd, &foo, sizeof(foo), 0); // DO NOT do this
Run Code Online (Sandbox Code Playgroud)
这将基本上将结构的所有内存转储company到您的套接字中.这WILL NOT WORK在这种情况下.即使它有点工作,这也是一个非常糟糕的主意.它不起作用的原因是vectors不直接包含数据.他们指着它.这意味着当您将包含向量的结构转储到套接字中时,您将转储指向内存的指针,但不会转向指向的内容.这将导致接收方(最多)崩溃.
它对个人person或car物体有用.它们不包含任何指针,因此它们的内存包含所有相关值
在发送方:
person joe = { "Joe", 35 };
send(sockfd, &joe, sizeof(joe), 0); // may work, but is a bad idea, see below
Run Code Online (Sandbox Code Playgroud)
在接收方:
person joe;
recv(sockfd, &joe, sizeof(joe), 0);
Run Code Online (Sandbox Code Playgroud)
但是,这仍然是一个坏主意.它依赖于发送方和接收方,它们的结构具有完全相同的存储器布局.出于各种原因,这可能不是真的.有些包括一个在PowerPC芯片上,另一个在Intel x86芯片上.或者一个在使用Visual Studio编译的Windows机器上,另一个在使用gcc编译的Linux机器上.或许有人调整了一些编译器标志,导致默认结构布局不同.有很多原因.
真的,你应该像这里所提出的每个人一样使用序列化框架.我会建议谷歌协议缓冲区或其他人已经链接到的Boost序列化框架.但还有很多其他的.
另一个序列化框架应该被提及,因为它非常快(几乎与直接将结构的内存映像转储到套接字中一样快)是Cap'n Proto.
如果你要做很多这些,你可能想要看看Thrift.它将自动生成所有必要的代码,以便为您序列化所有结构,因此您无需手动执行此操作.
他们支持字符串也非常实用.
哦! 它是免费的.8-)
另外,它会发送二进制数据,因此您不必将数字转换为字符串,反之亦然.如果您的大部分数据都不是字符串,那么这样做要快得多.
使用Boost序列化库:
http://www.boost.org/doc/libs/1_48_0/libs/serialization/doc/index.html
对于此类任务而言,这可能是最强大,通用,可靠,易于使用甚至跨平台的方式.
正如其他人已经说过的那样,使用某种序列化库将提供最强大(也可能是最简单的维护)解决方案.但是,如果您真的想要自己实现它,那么以下显示了如何处理它的"想法".以下分配缓冲区,然后使用employees矢量内容填充它.c假设变量是类型的company.
有些事情需要注意:
htonl用于以网络字节顺序存储整数值.接收端应该ntohl用来读出它们.简单而非常不完整的例子:
// allocate buffer to store all the data for a send. In a real world
// this would need to be broken up into appropriately sized chunks
// to avoid difficulties with UDP packet fragmentation.
// This likely over-allocates because the structure likely has padding
char *buf = new char[ sizeof( uint32_t ) + // for total number of entries
sizeof( person ) * c.employees.size() ]; // for each entry
char *pos = buf;
// Indicate how many are being sent
*(uint32_t*)pos = htonl( c.employees.size() );
pos += sizeof uint32_t;
for ( vector<person>::iterator pi = c.employees.begin();
pi != c.employees.end(); pi++ )
{
*(uint32_t*)pos = htonl( pi->age );
pos += sizeof uint32_t;
strcpy( pos, pi->name );
pos += strlen( pi->name ) + 1;
}
send( 0, buf, (int)( pos - buf ), 0 );
delete [] buf;
// The receiving end would then read the number of items and
// reconstruct the structure.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18766 次 |
| 最近记录: |