在socket上发送struct时序列化问题

我正在开发基于UDP的客户端/服务器我想从服务器向客户端发送不同的消息。 为每条消息定义了不同的C结构。

我想了解我序列化数据的方式有什么问题。

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

序列化/反序列化function

 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]; } 

发件人端代码序列化结构

 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; icCnt; i++) msg = serialize_int(msg,t->cId[i*4]); for(int i=0; idata[i]); return msg; } 

接收方端代码以反序列化数据

 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 

问题1:
为什么反序列化的值与预期的不一样?

问题2:
序列化/反序列化方法与memcpy有何不同?

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

编辑

调用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 } 

存储在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在serializeTask()有2个问题

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

应该是(假设i应该是idata)

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

第一个for循环序列化每隔4个cId[] 。 OP肯定想序列化连续的cId[]
仅序列化data字符串的长度。 OP当然希望序列化所有这些 NUL终止字节。


发布的缓冲区中的数据更可能是下面的,这与序列化代码匹配。 这意味着填充Task* t的更高级代码是错误的。 我相信在字段mTypetkType中看到的值是指针或float ,在序列化之前, Task* t很可能tkType

 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 ...