1

CでTCPソケットプログラミングを使用してクライアントサーバープログラム通信を実装しようとしています。これは、LinuxOSがインストールされている2台の64ビットマシン間です。2つのプロセス間でc-structを転送したいと思います。

このために、私はパックを使用してみました-unpack()機能。

次のコードスニプトを検討してください

/*---------------------------------------------------------
on the sending side I have: 
---------------------------------------------------------*/

struct packet {
 int64_t x;
 int64_t y;
 int64_t q[maxSize];
} __attribute__((packed));

int main(void)
{
 // build packet
 struct packet pkt;
 pkt.x = htonl(324);
 pkt.y = htonl(654);
 int i;
 for(i = 0; i< maxSize; i++){
    pkt.q[i] = i; **// I also try pkt.q[i] = htonl(i);**
 }
  // and then do the send
}

/*-----------------------------------------------------------------------------
 in the receiving side: 
 -----------------------------------------------------------------------------*/
struct packet {
 int64_t x;
 int64_t y;
 int64_t q[maxSize];
} __attribute__((packed));

static void decodePacket (uint8_t *recv_data, size_t recv_len)
{
 // checking size
 if (recv_len < sizeof(struct packet)) {
     fprintf(stderr, "received too little!");
     return;
 }

struct packet *recv_packet = (struct packet *)recv_data;

int64_t x = ntohl(recv_packet->x);
int64_t y = ntohl(recv_packet->y);
int i;
printf("Decoded: x=%"PRIu8" y=%"PRIu32"\n", x, y);

 for(i=0;i<maxSize;i++){
  **//int64_t res = ntohl(recv_packet->q[i]);  I also try to print res**          
  printf("%"PRIu32"\n" , recv_packet->q[i]);     
 }
} 

int main(int argc, char *argv[]){
 // receive the data and try to call decodePacket()
 int8_t *recv_data = (int8_t *)&buf; //buf is the data received
 size_t recv_len = sizeof(buf);
 **decode_packet(recv_data, recv_len);**  
}

//-----------------------------------------------------------------------------

ここで問題となるのは、構造体でxとyの値を正しく受け取っていることですが、構造体の配列qで、メモリグラブ値の可能性がある奇妙な数値を受け取っています(memset()を使用して反対側からデータを受信する前にゼロで配列します。この場合、すべてのゼロの値が受信されます)

構造体の配列の正しい値を受け取っていない理由がわかりません。

構造体を配置する前に配列を埋めるときにhtonl()を使用して、または使用せずに、反対側で:構造体から配列をデコードするときにntohl()を使用して使用することに注意してください。

どんな助けでもありがたいです、

4

2 に答える 2

3
size_t recv_len = sizeof(buf);
decode_packet(recv_data, recv_len);

このコードは、間違ったサイズがに渡されることを保証しdecode_packetます。したがって、decode_packetチェックを続けるrecv_len < sizeof(struct packet)と、そのテストは無意味になります。受信したバイト数に関係なく、常に合格します

呼び出しによって返された値からサイズをフェッチする必要がありrecvます。私の最善の推測は、実際にあなたが期待しているよりも少ないバイトを受け取っているということです。


構造体の送受信は非常に便利ですが、多くの場合、無駄な作業になります。データを手動でシリアル化するか、いくつかの明示的なメカニズムを使用するのがおそらく道です。

于 2012-08-07T17:16:52.017 に答える
1

sendあなたは私たちにとの部分を見せませんでしたrecv、それは間違っている可能性が高いです。私の推測では、配列の最初のアイテムを正しく受け取っていて、それらはある時点でゴミに「なり」ますよね?

ええと、@ cnicutarは正しいですが、少し拡張させてください...

まず、呼び出すsendときは、戻り値を調べて、すべてのバイトが送信されたかどうかを確認する必要があります。構造が大きい場合(たとえば、基になるソケットバッファーよりも大きい場合)、構造全体を送信するために複数の呼び出しが必要になります。と同じようにrecv、 1回の呼び出しでメッセージ全体recvを受け取ることを期待しないでください。また、対応する呼び出しrecvによって送信されたのと同じ量のデータをすべての人が受け取ることを期待しないでください。send受信したバイト数を常に確認recvし、必要に応じて再度呼び出します(着信バッファー内の適切な場所をポイントし、受信するバイト数を減らします)。

したがって、おそらく何が起こっているのか、十分なデータを受信して​​おらず(おそらくすべてを送信していない)、着信バッファの最初の部分だけがいっぱいになっています。したがって、構造の残りの部分はガベージであるか、(呼び出したときにmemset)ゼロで初期化されたままになります。

また、負の値が可能であるためではなく、両方sendに注意してrecv戻ります(エラーを示すため)。ssize_tsize_t

于 2012-08-07T23:07:19.643 に答える