2016-10-14 19 views
0

こんにちは私は問題にまっすぐにさせてください。私は、クライアントがJavaのtcpソケットが正しく受信されません

を認証された後、サーバーがこのクライアントに送信する大きなJSONパケットを持っている。しかし、それは分割または何かの例だようにパケットが戻って奇妙な方法で来る:

JSONは次のようになります。

それが伝わってくるとき
Received: {"UserID":1,"PlayerID":2,"EXP":0,"Lvl":1,"Coins":0,"ItemSlots":30} 

:それはクライアントに来るとき

Received: {"UserID":1,"PlayerID":2,"EXP":0,"Lvl":1,"Coins":0, 
Received: "ItemSlots":30} 

は、なぜそれがパケットか何かを分割しないとどのように私はとにかくこの問題を解決することができますか?

Javaがコードを受信:

private class ClientThread extends Thread { 
     public void run() { 
      try { 
       while (selector.select() > 0) { 
        for (SelectionKey sk : selector.selectedKeys()) { 

         selector.selectedKeys().remove(sk); 
         if (sk.isReadable()) { 

          SocketChannel sc = (SocketChannel)sk.channel(); 
          ByteBuffer buff = ByteBuffer.allocate(1024); 
          String content = ""; 

          while (sc.read(buff) > 0) { 
           sc.read(buff); 
           buff.flip(); 
           content += charset.decode(buff); 
           buff.clear(); 
          } 

          System.out.println("Recieved: " + content); 
          sk.interestOps(SelectionKey.OP_READ); 
         } 
        } 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

おかげで素晴らしい一日を過ごします。

+0

ByteBufferのサイズを2048に増やしてみてください。 –

+0

私はそれを試してみましたが、大規模なパケットではありませんでした。私は大きなパケットに対して何らかのコードが必要だと思います。 – Premt

+0

試してみてください:ByteBuffer.allocate(2048);あなたのコードで –

答えて

1

こんにちはレム私は、クライアントが

を認証されるサーバはあなたが大きなJSON メッセージを持っている意味、このクライアントに送信する大きなJSONパケットを得ましたので、まっすぐな問題に着きます。パケットは、ネットワークプロトコルが情報を交換するために使用したものです。

しかし、パケットの分割または何かの例のような奇妙な形で戻ってくる:

あなたはワイヤーを見ている場合を除き、あなたはパケットを見ていません。あなたは、あなたがTCP接続の終わりから得たバイトを見ています。

JSONあるべき:

受け取っ:{ "ユーザID":1、 "PlayerID":2、 "EXP":0、 "LVL":1、 "コイン":0、 "ItemSlots ":30}

それが伝わってくる。

受け取っ:{" ユーザID ":1、" PlayerID ":2、" EXP ":0、" LVL ":1、" コイン」:0、 受領: "ItemSlots":30}

優れています。あなたは同じバイトを持っています。次に、メッセージの終わりを特定して解析するJSONパーサを作成します。

なぜそれがクライアント

に来るときには、TCPが相手側にメッセージを取得する方法ですので、それはパケットにメッセージを分割パケットか何かを分割しません。 TCPはメッセージプロトコルではなく、アプリケーションがメッセージとみなしていることを知らない、または気にしません。これがアプリケーションの仕事です。

とにかくこれを修正できますか?

メッセージがどこで終了するかを把握するJSONパーサーを作成します。まだJSON over TCPを受け取るコードは実装されていないので、それまでは動作しません。

TL; DR:アプリケーションレベルのメッセージプロトコルが必要な場合は、実装する必要があります。 TCPは1つではありません。

1

TCPプロトコルはメッセージの境界を維持しません。サーバーが送信するものは、クライアントがそのまま受け取り、その逆も保証されません。

サーバーが1000バイトのデータを送信する場合、クライアントアプリケーションは複数のrecvまたは単一のrecvに同じデータを受信できます。 TCPは動作を保証しません。 「分割」が発生する可能性があります。複数のチャンクに入ってくるデータを処理するアプリケーションまであり、それをさらに処理するためにアプリケーションデータの1つの単位に統合します。特に大きなデータサイズでは、これを見ることができます。

1

ノンブロッキングソケットチャンネルがあるようです。つまり、ループは、sc.read(buff)が0を返すために終了しています。これは、送信されたデータの一部だけが受信されているためです。それはクライアントに来るとき

は、なぜそれが

パケットか何かを分割しないほとんどのデータは、二つ以上のパケットに分割されています。

とにかくこれを修正できますか?

ソケットがサーバーによって閉じられるまでバッファを満たしてください(この場合は、readは0を返す必要があります)。チャネルごとに別々のバッファを維持する必要があります。データの送信後にサーバが終了しない場合は、別の方法で記述する必要があります。例えば、JSONブロブの前にサイズヘッダを付けることができます。

関連する問題