2013-07-23 27 views
7

クライアント/サーバープログラムを開発していて、クライアントがサーバーにメッセージを送信する必要があります。Cでソケットを介して構造体を送信

サンプルメッセージC構造:デシリアライズデータ

if(recvfrom(sd, recvBuf, recvBufSize, 0, (struct sockaddr*)&clientAddr, &len) < 0) 
{ 
     printf("Error receiving message from client\n"); 
} 
else 
{ 
     printf("Message received:%s\n", recvBuf); 
     printf("Size :%d\n", strlen(recvBuf)); 
     memcpy(&regn, recvBuf, sizeof(regn)); 
     printf("PID:%d\n", regn.clientPid); 
     printf("MG:%s\n", regn.multicastGroup); 
} 
に構造体

struct Registration regn ; 
regn.clientPid = getpid(); 
strcpy(regn.multicastGroup, "226.1.1.1"); 

printf("PID:%d\n", regn.clientPid);   
printf("MG:%s\n", regn.multicastGroup); 
printf("Size:%d\n", sizeof(regn));   //Size is 28 

data = (unsigned char*)malloc(sizeof(regn)); 
memcpy(data, &regn, sizeof(regn)); 
printf("Size:%d\n", sizeof(data));   //Size is 4. 

Serverコードをシリアル化する

struct Registration 
{ 
char multicastGroup[24]; 
pid_t clientPid; 
}; 

クライアントコードスニペット

構造体をunsigned char *にコピーした後、配列のサイズは4になります。
データが配列に完全にコピーされないのはなぜですか?

サーバーは、char配列から構造体を再構築できません。
私が間違っていることを教えてください。

答えて

10

sizeof(regn)sizeof(data)が4バイトであるあなたのマシン上のポインタのサイズであるwherasあなたの完全な構造Registrationの大きさを与える(dataRegistration型のポインタでなければなりません)。式において

memcpy(data, &regn, sizeof(regn)); 
     ^ ^
     |  value variable of struct type 
     is pointer 

もprintf関数で、.は、例えば要素にアクセスするために使用され気付きますregn.multicastGroup

+0

このデータをソケット経由で送信したいとします。したがって、私は 'memcpy'それを' unsigned char * 'にしています – cppcoder

+0

@cppcoderあなたが' sizeof(struct registration) 'を使用して保存したデータのサイズをとる場合に使用します。 –

+0

@cppcoder' sendto() '? C –

3

同じエンディアンマシンで送信してrecvするとコードが機能しますが、クライアントとサーバーはclientPidを検査するときに一貫性を維持するためにホストからネットワークエンディアンへの変換を理想的に実行する必要があります。

+0

送信中に変数に 'htonl'を実行する方法を表示できますか? – cppcoder

0

移植性の理由から、プラットフォーム固有のエンディアンと構造体の埋め込みにより、各構造体メンバを個別にシリアル化することをお勧めします。

binn *obj; 

    // create a new object 
    obj = binn_object(); 

    // add values to it 
    binn_object_set_int32(obj, "clientPid", getpid()); // assuming it is 32 bits 
    binn_object_set_str(obj, "multicastGroup", "226.1.1.1"); 

    // send over the network 
    send(sock, binn_ptr(obj), binn_size(obj)); 

    // release the buffer 
    binn_free(obj); 

それはちょうど2つのファイル(binn.cとbinn.h)であるので、それは共有ライブラリとしてプロジェクト内でコンパイルの代わりに使用することができます。

はここBinnを使った例です。

メッセージの結合と断片化されたメッセージを避けるために、ソケットストリームでメッセージフレーミング(長さプレフィックスフレームとも呼ばれます)を使用する必要があります。

関連する問題