2011-10-28 13 views
0

私は現在、データグラム(udp)パケットを処理するcプログラムをいくつかのより高いレベルの言語に移植しようとしています。パケットは可変サイズである可能性があるので、それらのサイズを示す整数で始まります。 cでは、MSG_PEEKフラグを指定してrecvを呼び出し、最初にこの値だけを受け取ってからフィッティングバッファを割り当て、残りのパケットを読み込みます。コード(簡体字)はこのように書きます:高級言語のデータグラムパケットを覗くことは可能ですか?

// Simplified message format. 
struct message { 
    int length; 
    char[] text; 
} 
struct message *m = malloc (sizeof(int)); 

// Read out in just length. 
recv (sock, m, sizeof(int), MSG_WAITALL | MSG_PEEK); 
int txtlen = ntohl (m->length) * sizeof(char); 
int msglen = sizeof(int) + txtlen; 

// Read complete packet. 
m = realloc (m, msglen); 
read (sock, m, msglen); 
m->text[txtlen] = '\0'; 

// Show result. 
printf("%s\n", &m->text); 

私は巨大なバッファを確保するために、一見、共通の練習を避けたいと何ら大​​きなパケットが到着しないことを願っています。データグラムを覗いたり、pythonやjavaなどの高水準言語で可能な限り完全な長さを事前に決定するようなことはありますか?

+1

UDPパケットは「巨大」にすることはできません(例:http://stackoverflow.com/questions/1098897/what-is-the-largest-safe-udp-packet-size-on-the-internet)。あなたはこれについて心配するべきですか? – Mat

+0

*非常に限られたリソースを持つ組み込みシステムでない限り、間違いなく.. –

答えて

0

どうすればよいですか?

message = (struct message *)malloc(sizeof(struct message)); 
read(sock, &message->length, sizeof(int); 
message->length = ntohl(message->length); 
message->text = (char *)malloc(message->length + 1); 
read(sock, message->text, message->length); 
message->text[message->length] = 0; 
+0

残念ながら、これは2つのデータグラムを受け取るので動作しません。最初の読み込みでは、たとえint以上のものが含まれていても、データグラム全体が破棄されます。 – XZS

1

私は巨大なバッファを割り当てるために、一見、共通の練習を回避したいとパケットが文句を言わない任意の大きな得ることを願っています。

あなたはこれが何を意味するのかよく分かりません。 UDPパケットは一度にすべて到着するので、最初の整数はバッファの大きさを正確に示します。それが到着した後は「成長」しません。

あなたはヌル文字を追加しているので、あなたの長さの計算に、そのために考慮する必要があります:あなたはrealloc()を使用する場合

int msglen = sizeof(int) + txtlen + 1; 

は注意してください:

m = realloc (m, msglen); 

reallocがそれを失敗した場合mをnullに設定します。それはあなたが最初に割り当てられたメモリへの唯一の参照を失うことになるので、あなたはそれfree()にできることは決してないだろうことを意味します。あなたの構造を定義することができ、

void *tmp = realloc(m, msglen) 
if (tmp == null) { 
    // handle the error 
} 
m = tmp; 

をそして、あなたはデータを印刷するとき、m->textは、最初の文字のアドレスに評価され、あなたが

printf("%s\n", m->text); 

代わりに使用することができます。このような何かを試してみてください固定サイズで、

struct message { 
    int length; 
    char *text; 
} 

malloc()あなたのテキストバッファを割り当てるには:

struct message m; 
recv(sock, &m.length, sizeof(int), MSG_WAITALL | MSG_PEEK); 
m.text = malloc(m.length + 1); // +1 for the null that you'll append 
read(sock, m.text, m.length); 
m.text(m.length) = '\0'; 

printf("%s\n", m.text); 
free(m.text); 

あなたのプロジェクトで幸運を祈る - ネットワークプログラミングは常に学習体験です!

+0

コード例のreallocをチェックしないようにしました。上記のように、2回の読み込み呼び出しで2つのパケットが読み込まれるため、構造体が優先されます。 – XZS

+0

キャッチをありがとう!私は私の答えで訂正をしました。 –

0

UDP datagramsは64Kに制限されています(ネットワークで9000バイトまで可能性がありjumbo framesを、使用されていない限り)、そしてethernet framesは1500バイトです。プロトコルの設計者は、通常、すなわち未満1500バイトなので、ほとんどの場合、あなたの着信パケットが小さい、IP fragmentationを避けるようにしてください。

私は1472の静的バッファ(1500イーサネットフレーム長 - IPヘッダーの20バイト - UDPヘッダの8バイト)で開始します。あなたには、いくつかの任意のプロトコルに対処する必要がある場合 - 64Kにそれをつり上げます。あなたが余裕がない場合 - MSG_PEEKで実際のサイズを収集し、便利な平均値を見つけ、malloc(3)でフォールバック計画を設定します。

+0

私は、64Kの制限は、パケットの長さを示す16ビットの長さのUDPヘッダーフィールドに続くと予想しています。だからこれは本当に保存バッファを気にする必要があります。しかし、実際には、intを読み出すだけで、必要なメモリを事前に知ることができるということを考えると、64Kでも実際は無駄です。 – XZS

+1

はい、64Kは間違いなく無駄ですが、エンベデッド/リソースに制約のある環境にいない限り、この日や年齢では実際には問題にはなりません。 –

関連する問題