简体   繁体   English

通过套接字发送结构时的序列化问题

[英]Serialization issues while sending struct over socket

I am developing a Client/Server based on UDP I want to send different messages to the client from the server. 我正在开发基于UDP的客户端/服务器,我想从服务器向客户端发送不同的消息。 There are different C structures defined for each message. 每个消息定义了不同的C结构。

I would like to understand what is wrong in the way I am serializing the data. 我想了解序列化数据的方式出了什么问题。

struct Task
{
    int mType;
    int tType;
    int cCnt;
    int* cId;
    char data[128];
};

Serialization/Deserialization functions 序列化/反序列化功能

unsigned char * serialize_int(unsigned char *buffer, int value)
{
    buffer[0] = value >> 24;
    buffer[1] = value >> 16;
    buffer[2] = value >> 8;
    buffer[3] = value;
    return buffer + 4;
}

unsigned char * serialize_char(unsigned char *buffer, char value)
{
    buffer[0] = value;
    return buffer + 1;
}

int deserialize_int(unsigned char *buffer)
{
    int value = 0;

    value |= buffer[0] << 24;
    value |= buffer[1] << 16;
    value |= buffer[2] << 8;
    value |= buffer[3];
    return value;

}

char deserialize_char(unsigned char *buffer)
{
    return buffer[0];
}

Sender side code to serialize the structure 发送方代码以序列化结构

unsigned char* serializeTask(unsigned char* msg, const Task* t)
{
    msg = serialize_int(msg,t->mType);
    msg = serialize_int(msg,t->tkType);
    msg = serialize_int(msg,t->cCnt);
    for(int i=0; i<t->cCnt; i++)
            msg = serialize_int(msg,t->cId[i*4]);

for(int i=0; i<strlen(data); i++)
    msg = serialize_char(msg,t->data[i]);

    return msg;
}

Receiver side code to de-serialize data 接收方代码以反序列化数据

printf("Msg type:%d\n", deserialize_int(message) );
printf("Task Type:%d\n", deserialize_int(message+4) );
printf("Task Count:%d\n", deserialize_int(message+8));

Output 
Msg type:50364598         //Expected value is 3
Task Type:-2013036362     //Expected value is 1
Task Count:1745191094     //Expected value is 3  

Question 1: 问题1:
Why is the de-serialized value not same as expected? 为什么反序列化的值与预期的不同?

Question 2: 问题2:
How is serialization/de-serialization method different from memcpy? 序列化/反序列化方法与memcpy有何不同?

Task t;
memcpy(&t, msg, sizeof(t));  //msg is unsigned char* holding the struct data  

EDIT 编辑

Code which invokes serializeTask 调用serializeTask代码

void addToDatabase(unsigned char* message, int msgSize, Task* task)
{
    message = new unsigned char[2*msgSize+1];
    unsigned char* msg = message;  //To preserve start address of message
    message = serializeTask(message, task); //Now message points to end of the array

//Insert serialized data to DB
//msg is inserted to DB 
}

Serialized data stored in DB 存储在数据库中的序列化数据

Message:
00 
03 70 B6 88 03 70 B6 68 05 70 B6 68 05 70 B6 00 
00 00 00 00 00 00 00 A8 05 70 B6 AC 05 70 B6 B4 
05 70 B6 C9 05 70 B6 DE 05 70 B6 E6 05 70 B6 EE 
05 70 B6 FB 05 70 B6 64 65 66 00 63 6F 68 6F 72 
74 73 00 70 65 6E 64 69 6E 67 5F 61 73 73 69 67 
6E 5F 74 61 73 6B 73 00 70 65 6E 64 69 6E 67 5F 
61 73 73 69 67 6E 5F 74 61 73 6B 73 00 6D 65 73 
73 61 67 65 00 6D 65 73 73 61 67 65 00 3F 00 FF 
FF 00 00 FC 90 00 00 00 00 00 00 00 C9 2D B7 00 
00 00 00 10 06 70 B6 00 00 00 00 00 00 00 00 30 
06 70 B6 34 06 70 B6 3C 06 70 B6

OP has 2 problems in serializeTask() OP在serializeTask()有2个问题

for(int i=0; i<t->cCnt; i++)
  msg = serialize_int(msg,t->cId[i*4]); [i*4]
...
for(int i=0; i<strlen(data); i++)
  msg = serialize_char(msg,t->data[i]); strlen(data)

Should be (assuming i<strlen(data) should have been i<strlen(t->data) 应该是(假设i<strlen(data)应该是i<strlen(t->data)

for(int i=0; i<t->cCnt; i++)
  msg = serialize_int(msg,t->cId[i]);  // [i]
...
for(int i=0; i<strlen(t->data); i++)   // strlen(data) + 1
  msg = serialize_char(msg,t->data[i]);

The first for loop serialize every 4th cId[] . 第一个for循环每第4个cId[]序列化一次。 OP certainly wanted to serialize consecutive cId[] . OP当然想序列化连续的cId[]
Only the length of the data string was serialized. 仅将data字符串的长度序列化。 OP certainly wanted to serialize all that and a NUL terminating byte. OP当然想对所有这些 NUL终止字节进行序列化。


The data in the posted buffer is more likely the below, which does not match the serialization code. 发布的缓冲区中的数据更可能是以下内容,该数据与序列化代码匹配。 This implies the higher level code populating Task* t is wrong. 这意味着填充Task* t高级代码是错误的。 I am confident that the values seen in fields mType and tkType are either pointers or float , again Task* t is likely amiss before the serialization. 我相信,在mTypetkType字段中看到的值要么是指针,要么是float ,再次Task* t在序列化之前很可能不存在。

0xb6700300 or -3.576453e-06
0xb6700388 or -3.576484e-06
0xb6700568 or -3.576593e-06
0xb6700568 or -3.576593e-06
0x000000 or 0.000000e+00
0x000000 or 0.000000e+00
0xb67005a8 or -3.576608e-06
0xb67005ac or -3.576609e-06
0xb67005b4 or -3.576611e-06
0xb67005c9 or -3.576615e-06
0xb67005de or -3.576620e-06
0xb67005e6 or -3.576622e-06
0xb67005ee or -3.576624e-06
0xb67005fb or -3.576627e-06
def\0cohorts\0pending_assign_tasks\0pending_assign_tasks\0message\0message\0?\0
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM