msg->msgType = JOINREPLY;
memcpy((char *)(msg+1), &memberNode->addr.addr, sizeof(memberNode->addr.addr));
memcpy((char *)(msg+1) + 1 + sizeof(memberNode->addr.addr), &memberNode->memberList, sizeof(memberNode->memberList));
这是我想通过调用另一个函数从一个函数发送的消息,send((char *)msg, msgsize);
msg的数据结构是
enum MsgTypes{
JOINREQ,
JOINREPLY,
DUMMYLASTMSGTYPE,
HEARTBEAT
};
typedef struct MessageHdr {
enum MsgTypes msgType;
}MessageHdr;
vector<MemberListEntry> memberList;
是memberList的定义,因为你可以看到memberList是一个MemberListEntry类型的向量,MemberListEntry有自己的数据。
int id;
short port;
long heartbeat;
long timestamp;
由于我将完整的memberList转换为(char *),是否可以再次将(char *)转换为memberList或MemberListEntry类型并迭代它?
MemberListEntry *ml;
ml=(MemberListEntry *)malloc(sizeof(MemberListEntry));
for(char *j=finalData; i < (int)string(finalData).length(); j = (char *)(j+ sizeof(MemberListEntry))){
ml= (MemberListEntry *)j;
i+=sizeof(MemberListEntry);
idR=ml->getid();
portR=ml->getport();
heartbeatR=ml->getheartbeat();
//Do some stuff
}
&#34; finalData&#34;切断msgType和我正在存储的地址后得到的数据,指针指向我以char格式存储我的memberList的位置。
答案 0 :(得分:1)
您需要在邮件标题中包含一个字段,指明邮件包的整个大小。
可能是这样的:
typedef struct MessageHdr {
enum MsgTypes msgType;
unsigned int msgLength;
} MessageHdr;
存储在msgLength字段中的实际值取决于约定,例如它可以从整个邮件包大小或减去标题的大小,或简单地MemberListEntry
的计数。使用你喜欢的任何东西。
您使用send((char *)msg, msgsize);
通过tcp套接字发送。但是,您的对等方无法确定重要的msgsize
值以重建消息数据,除非您明确将其作为邮件头的一部分发送。
然后重建它们应该是微不足道的。
首先,您应该弄清楚消息包中存在多少条目。然后你分配一个这个大小的新矢量。最后你将memcpy
所有数据都放入新的载体中,一切都应该没问题。
原则#1:您无法从任何地方获取信息。
sizeof
有效,因为编译器知道大小。 它们是由规范,平台或您#include
d的头文件预定义的。他们是固定的。他们永远不会改变。
.length()
有效,因为 std::vector
会在场景下保留您的长度信息。您可以自行检查相应的标题文件。
简而言之,它们都不是来自某些花哨的魔法,它会自动找出仲裁记忆区域中的内容。
在您的情况下,信息 - &#34;实际元素数&#34; - 很关键。并且对等体必须可以访问它才能重建数据结构。
原则#2:包含指针的数据结构不能直接通过网络发送。
指针仅在当前进程中有效。你不能盲目地通过网络发送指针。所以发送你聪明的std::vector
也行不通。虽然std::vector
本身具有固定的大小,您可以对其应用sizeof
,但它在内部使用指针来保存可以动态更改的实际数据。
那么,你真正需要的是某种数据编组/对象序列化。您需要将数据转换为适合网络传输的某种表示形式,并在以后将其转换回来。在C ++领域,你必须自己做。没有魔力。
如果您觉得实现这样的事情真的很无聊,请考虑使用一些处理对象序列化的高级语言。例如,Javascript本身支持着名的JSON格式,这种格式在数据交换方面非常出色。或者你可以使用C#,它有一个快速高效的二进制序列化器,类型很强。
答案 1 :(得分:0)
如果你需要使用char *传输数据,只要你知道它的大小,就可以简单地将数据重新设置回原始形式,假设没有数据变形或转换,TCP会阻止这些数据。
char*
实际上是一种伪装的数组,因为数组实际上只是在内存中相邻存储的数据块。在C:
array[1] and 1[array]
与访问数据地址的数据增加1相同。
因此,您的数据刚刚“未格式化”为原始数据块。如果你使用演员表回原始表格给它类型,一切都应该没问题。
如果你的数据包含指针,你就搞砸了。现在您没有要引用的原始内存地址系统,那么如何定位数据呢?除非您复制内存地址,否则一旦跨越系统,就无法访问指针。