1

以前のスタック オーバーフローの質問では、Akka ソケット サーバーを構築しているときに、私の方法の誤りを示すのに非常に役立ちました。実際に、次のフレーミングでメッセージを送信できる Akka ソケット クライアントがあります。

メッセージ長: 4 バイト メッセージ タイプ: 4 バイト メッセージ ペイロード: (長さ) バイト

メッセージの送信に使用している iOS コードは次のとおりです。

 NSInputStream *inputStream;
    NSOutputStream *outputStream;

    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"localhost", 9999, &readStream, &writeStream);
    inputStream = (__bridge_transfer NSInputStream *)readStream;
    outputStream = (__bridge_transfer NSOutputStream *)writeStream;

    [inputStream setDelegate:self];
    [outputStream setDelegate:self];

    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

   // [inputStream open];
    [outputStream open];
    NSLog(@"NSData raw zombie is %d bytes.", [rawZombie length]);
    uint32_t length = (uint32_t)htonl([rawZombie length]);
    uint32_t messageType = (uint32_t)htonl(1);        

    NSLog(@"Protobuf byte size %d", zombieSighting->ByteSize());

    [outputStream write:(uint8_t *)&length maxLength:4];
    [outputStream write:(uint8_t *)&messageType maxLength:4];
    [outputStream write:(uint8_t *)[rawZombie bytes] maxLength:length];

    [outputStream close];

「rawZombie」変数 (NSData *) は、次のメソッドから取得されます。

- (NSData *)getDataForZombie:(kotancode::ZombieSighting *)zombie {
    std::string ps = zombie->SerializeAsString();
    NSLog(@"raw zombie string:\n[%s]", ps.c_str());
    return [NSData dataWithBytes:ps.c_str() length:ps.size()];
}

私が見ている症状は、iOS から送信されたメッセージを受信し、メッセージ タイプ (1) と同様に長さが正しく、本文が問題なく表示されることです。Scala protobufs を使用する Akka サーバーは、メッセージを逆シリアル化し、メッセージのすべての値を完全に出力します。問題は、そのメッセージを受け取った直後に、Akka サーバーが別のメッセージを受け取ったと見なすことです (明らかに、ストリームにさらにデータが入ってきました)。最後のデータは、iOS アプリを実行するたびに同じではありません。

たとえば、2 つの連続したメッセージ受信からのトレース出力を次に示します。

received message of length 45 and type 1
name:Kevin
lat: 41.007
long: 21.007
desc:This is a zombie
zombie type:FAST
received message of length 7 and type 4
received message of length 45 and type 1
name:Kevin
lat: 41.007
long: 21.007
desc:This is a zombie
zombie type:FAST
received message of length 164 and type 1544487554

つまり、Akka サーバーがメッセージの適切なデータを受信した直後に、ランダムな任意のがらくたも受信することがわかります。この余分な恣意的ながらくたなしでAkkaクライアントが適切に動作していることを考えると、protobufオブジェクトをNSStreamに書き込む方法に何か問題があると思います...誰かが私の愚かな間違いを見つけることができますか?ここで起こっています。

4

1 に答える 1

2

血まみれの地獄。これを見なかったなんて信じられない。ここのコード行で:

[outputStream write:(uint8_t *)[rawZombie bytes] maxLength:length]

送信する最大バイト数に値「長さ」を使用しています。残念ながら、その値は、ネットワーク経由での送信に備えて、すでに「エンディアン」の順序が反転されています。「長さ」を [rawZombie length] に置き換えたところ、魅力的に機能しました。

:(

于 2013-02-03T20:25:46.963 に答える