0

作成中のアプリでのパケットの解釈に関して、かなり複雑な問題があります。ホスト アプリは、次の構造のパケットをクライアント アプリに送信します。

[10 バイトのヘッダー][可変バイト長の選択されたクライアントのピア ID][空バイト][可変バイト長のクライアントのピア ID][空バイト][4 バイトの整数][可変バイト長のクライアントのピア ID][空のバイト][4 バイトの整数]

この構造で生成されるサンプル パケットを次に示します。

434e4c50 00000000 006a3134 31303837 34393634 00313233 38313638 35383900 000003e8 31343130 38373439 36340000 0003e8

変換すると、次のようになります。

CNLP j1410874964 1238168589 Ë1410874964 Ë

「CNLP j」は10バイトのパケットヘッダです。「1410874964」は、選択したクライアントの peerID です。「1238168589」は別のクライアントの peerID です。"Ë" の int 値は 1000 です。"1410874964" は、他のクライアント (この場合は選択されたクライアント) の peerID です。" Ë" にも 1000 の int 値があります。基本的に、このパケットでは、選択されたクライアントと、各クライアントに関連付けられた int 値という 2 つのことを伝えています。

私の問題は解釈側(クライアント側)にあります。この特定のタイプのパケットを解釈するには、次の方法を使用します。

    + (NSMutableDictionary *)infoFromData:(NSData *)data atOffset:(size_t) offset
{
    size_t count;

    NSMutableDictionary *info = [NSMutableDictionary dictionaryWithCapacity:8];

    while (offset < [data length])
    {
        NSString *peerID = [data cnl_stringAtOffset:offset bytesRead:&count];
        offset += count;

        NSNumber *number = [NSNumber numberWithInteger:[data cnl_int32AtOffset:offset]];
        offset += 4;

        [info setObject:number forKey:peerID];
    }

    return info;
}

通常、これらの各パケットの範囲は 49 ~ 51 バイトです。「オフセット」は、以前のメソッドで設定され、パケット ヘッダーの後のバイト数と、選択されたプレーヤーの後の空のバイト (上記のパケットの場合は 21) を反映します。"count" は値 1 で初期化されます。この特定の例の場合、長さは 51 です。次のメソッドには上記の引数が渡されます。

    - (NSString *)cnl_stringAtOffset:(size_t)offset bytesRead:(size_t *)amount
{
    const char *charBytes = (const char *)[self bytes];
    NSString *string = [NSString stringWithUTF8String:charBytes + offset];
    *amount = strlen(charBytes + offset) + 1;
    return string;
}

このメソッドは、パケット内の可変長文字列を読み取り、オフセットを peerID 文字列の後ろにある空のバイト パッドの直後のバイトに設定し、読み取った文字列を返すことになっています。次に、「amount」は、メソッドが文字列を読み取ったバイト数に設定されます (これは、最初のメソッドに戻った後の count の新しい値になります)。次に、「オフセット」と「カウント」が加算されて、新しい「オフセット」になります。ここで、パケットの int 部分の解釈が開始されます。上記の引数は、次のメソッドに渡されます。

- (int)cnl_int32AtOffset:(size_t)offset
{
    const int *intBytes = (const int *)[self bytes];
    return ntohl(intBytes[offset / 4]);
}

このメソッドは、パケットの現在のオフセット値で読み取った 32 ビット (4 バイト) の int 値を返すことを目的としています。オフセットが 4 で割り切れない数値の場合、このメソッドに問題があると思います。この場合、最初の int 値 1000 が正しく解釈され、while の最初の反復中にオフセットとして 32 が返されました。ループ。ただし、2 回目の繰り返しでは、解釈された int 値は 909377536 でした (バイト 000003E8 ではなく、パケット内のバイト 36340000 を読み取ることから取得)。 . 上記のカテゴリの 32 ビット int を解釈した後、4 バイト (32 ビット int) を考慮して、最初のメソッドのオフセットに 4 が追加されます。ゼロで割り切れないオフセットに関する私の直感が正しければ、この問題を回避するための提案は大歓迎です。私はかなり長い間この問題を解決する方法を探していましたが、おそらく新鮮な目が役立つかもしれません. 助けてくれてありがとう!!!

4

1 に答える 1