2

UDP に基づいてクライアント/サーバーを開発しています。サーバーからクライアントにさまざまなメッセージを送信したいと考えています。メッセージごとに異なる C 構造体が定義されています。

データをシリアル化する方法の何が問題なのかを理解したいと思います。

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

シリアライゼーション/デシリアライゼーション関数

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

データを逆シリアル化する受信側コード

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
4

1 に答える 1

0

OPには2つの問題があります serializeTask()

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)

あるべきです(あるべきだったと仮定し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]);

最初の for ループは 4 番目ごとにシリアル化しますcId[]。OPはやっぱり連載したかったなぁcId[]
文字列の長さだけdataがシリアル化されました。OPは確かにそのすべてとNUL終了バイトをシリアライズしたかったのです。


ポステッド バッファ内のデータは、シリアライゼーション コードと一致しない以下の可能性が高いです。これは、上位レベルのコードの入力Task* tが間違っていることを意味します。mTypefieldsおよびで見られる値tkTypeは、ポインタまたは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
...
于 2013-09-09T18:49:15.307 に答える