2

次のパケット形式があります。

   1B       4B      1B    1B    string   2 bytes    1B      string  
+------+----------+---+--------+---~~--+---------+--------+---~~---+
| type | lifetime | 2 | length | Name  | Counter | length |  Data  |
+------+----------+---+--------+---~~--+---------+--------+---~~---+

typedef struct pkt_data {
    u_char pkt_type;
    u_int lifetime;
    u_char type;
    u_char len_name;
    u_char name[100];
    u_short counter;
    u_char len_data;
    u_char data[200];
}__attribute__((__packed__)) Data;

パケットを構築して解析するためのコードは次のとおりです。

int buildDataPacket(u_int _lifetime, u_char* _name, u_short _counter, u_char* _data, u_char* _dataPacket) {
    Data *ndata=NULL;
    u_char *ptr;

    memset(_dataPacket, 0, 512);

    ndata = (Data *) _dataPacket;
    ndata->pkt_type = 2;
    ndata->lifetime = htonl(_lifetime);
    ndata->type = 2;
    ndata->len_name = strlen(_name);

    ptr = (u_char *)ndata + (3 * sizeof(u_char)) + sizeof(u_int);
    strncpy((char *)ptr, (char *)_name, strlen(_name));

    u_short counter = htons(_counter);
    u_char datalen = strlen(_data);

    ptr = ptr + strlen(_name);
    memcpy(ptr, &counter, sizeof(u_short));
    ptr = ptr + sizeof(u_short);
    memcpy(ptr, &datalen, sizeof(u_char));
    ptr = ptr + sizeof(u_char);
    strncpy((char *)ptr, (char *)_data, strlen(_data));
    ptr = ptr + strlen(_data);

    return (ptr - (u_char *)_dataPacket);
}

int processDataPacket(u_char* _dataPacket, u_short _pktLen)
{
    if (!_dataPacket || !_pktLen) {
            return -1;
    }

    Data *dataPkt;
    dataPkt = (Data *)_dataPacket;

    printf("Lifetime: %d\n", ntohl(dataPkt->lifetime));
    printf("Name: %s\n", dataPkt->name);
    printf("Counter: %d\n", dataPkt->counter);
    printf("Data: %s\n", dataPkt->data);

    return 0;
}

Wireshark でパケットのスニッフィングを行ったところ、パケットの構成がフォーマットに従っていることがわかりました。しかし、「カウンター」と「len_data」の値は、それに応じて設定してもゼロです。また、パケットを受信すると、完全なパケットがバッファに保存されません。

rval=recvfrom(inet_sock, buf, BUFLEN-1, MSG_DONTWAIT, (struct sockaddr *) &dest_sin, &socklen);

buf[rval]=0;
fprintf(stderr, "Received: %d (%d) bytes containing %s", rval, strlen(buf), buf);

「rval」は正しい合計バイト数を返しますが、「buf」は「name」の後で終了します。strlen(buf) は、名前までのパケットの長さのみを返します。したがって、processDataPacket の「データ」は空です。このパケットを構築して解析する方法を教えてください。

4

1 に答える 1

2
ptr = ptr + strlen(_name);
memcpy(ptr, &counter, sizeof(u_short));

これは間違っています。ポインターの位置を正確にstrlen(_name)進める必要がある場合にのみ、ポインターの位置を進めています。100_nameu_char name[100]

サイドノート:

  • u_int lifetime;4 バイトであるとは限りません。そのために使用uint32_tします。同じことがu_short(を使用uint16_t)にも当てはまります

strlen(buf) はパケットの長さを返します

パケットは単なる大きな文字列ではない ( などの非テキスト データも含まれている) ため、最初のバイトで停止するものu_int lifetimeを使用することはできません。strlen0

于 2012-04-23T21:27:50.900 に答える