我可以在将对象转换为(char *)后检索它

时间:2015-03-22 03:58:49

标签: c++ pointers casting char

        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的位置。

2 个答案:

答案 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相同。

因此,您的数据刚刚“未格式化”为原始数据块。如果你使用演员表回原始表格给它类型,一切都应该没问题。

如果你的数据包含指针,你就搞砸了。现在您没有要引用的原始内存地址系统,那么如何定位数据呢?除非您复制内存地址,否则一旦跨越系统,就无法访​​问指针。