0

現在、データグラム (udp) パケットを処理する ac プログラムを高水準言語に移植しようとしています。パケットは可変サイズになる可能性があるため、サイズを示す整数で始まります。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 などの高水準言語で可能ですか?

4

3 に答える 3

1

巨大なバッファを割り当てるという一見一般的な方法を避け、パケットがこれ以上大きくならないことを望みます。

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

null 文字を追加しているため、長さの計算でそれを考慮する必要があります。

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

使用するときは注意してくださいrealloc()

m = realloc (m, msglen);

realloc失敗すると、null に設定されmます。つまり、最初に割り当てられたメモリへの唯一の参照が失われるため、決して参照できなくなります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);

あなたのプロジェクトがうまくいきますように。ネットワーク プログラミングは常に学習体験です。

于 2011-10-28T12:14:44.640 に答える
0

UDP データグラムは 64K に制限されており、イーサネット フレームは 1500 バイトです (ネットワークがジャンボ フレームを使用していない限り、最大 9000 バイトになる可能性があります)。プロトコルの設計者は通常、IP フラグメンテーションを回避しようとするため、着信パケットは小さい、つまり 1500 バイト未満である可能性が高くなります。

1472 の静的バッファーから始めます (1500 イーサネット フレーム長 - 20 バイトの IP ヘッダー - 8 バイトの UDP ヘッダー)。任意のプロトコルを処理する必要がある場合は、最大 64K に増やしてください。余裕がない場合は、 で実際のサイズを収集しMSG_PEEK、便利な平均値を見つけて、 でフォールバック プランを設定しますmalloc(3)

于 2011-10-28T12:44:02.583 に答える
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;
于 2011-10-28T11:56:55.877 に答える