は、私はこのような構築基本的にされているJava NIOチャネルを介して、データのストリームを送信読まれていませんパケットidはそれを解析する方法を指示する)。一部のデータをローカルに送信しようとするとうまくいきますが、Windows Server 2012で実行しようとすると、負の値や大きすぎる値などの無効なパケットサイズの値が読み取られます。のJava NIOチャネルデータが正しく
クライアント出力:最後に
Sending packet: network.PacketChunkRequest (size: 24)
Sending packet: network.PacketChunkRequest (size: 24)
Sending packet: network.PacketChunkRequest (size: 24)
Sending packet: network.PacketChunkRequest (size: 24)
Sending packet: network.PacketChunkRequest (size: 24)
Sending packet: network.PacketChunkRequest (size: 24)
Sending packet: network.PacketChunkRequest (size: 24)
Sending packet: network.PacketChunkRequest (size: 24)
Sending packet: network.PacketChunkRequest (size: 24)
2988
-2032198748
java.lang.IllegalArgumentException
at java.nio.ByteBuffer.allocate(Unknown Source)
at network.ClientSocket.run(ClientSocket.java:66)
at java.lang.Thread.run(Unknown Source)
数字は、あなたがそれのためにバッファを準備しようとしているときに例外につながり、1つのとんでもない数に気づくことができ、読み取りパッケージの大きさ、です。
サーバー出力:
Sending packet: network.PacketLoginAck (size: 16)
Sending packet: network.PacketPlayerData (size: 951)
Sending packet: network.PacketWorldInfo (size: 33)
Received packet: network.PacketChunkRequest (size: 24)
Sending packet: network.PacketChunkData (size: 2988) // This is the first package that still worked
Received packet: network.PacketChunkRequest (size: 24)
Received packet: network.PacketChunkRequest (size: 24)
Received packet: network.PacketChunkRequest (size: 24)
Received packet: network.PacketChunkRequest (size: 24)
Received packet: network.PacketChunkRequest (size: 24)
Received packet: network.PacketChunkRequest (size: 24)
Received packet: network.PacketChunkRequest (size: 24)
Received packet: network.PacketChunkRequest (size: 24)
Sending packet: network.PacketChunkData (size: 2518)
Sending packet: network.PacketChunkData (size: 2741)
Sending packet: network.PacketChunkData (size: 2966)
Sending packet: network.PacketChunkData (size: 2449)
Sending packet: network.PacketChunkData (size: 2769)
Sending packet: network.PacketChunkData (size: 1862)
Sending packet: network.PacketChunkData (size: 2526)
Sending packet: network.PacketChunkData (size: 2353)
PacketChunkRequestはPacketChunkDataまた、これらの2つのintを含むが、2つのint、二つの座標が含まれ、プラス続くデータの長さを記述する整数であるバイナリデータ、実際のデータ
私はこのように私のデータを送信します。
for(Packet p : packets) {
System.out.println("Sending packet: "+p.getClass().getName()+" (size: "+p.length()+")");
ByteBuffer b = p.getBuffer();
while (b.hasRemaining()) {
clientChannel.write(b);
}
b.clear();
sentPackages.add(p);
}
これは、パケットを読み込むためのコードです:
List<ByteBuffer> packets = new ArrayList<ByteBuffer>();
ByteBuffer bin = null;
int packetLength = 0;
while((bytesRead = channel.read(buffer)) > 0) {
buffer.flip();
while(buffer.remaining() > 0) {
if(packetLength == 0) {
if(buffer.remaining() < 4) break;
packetLength = buffer.getInt();
System.out.println(packetLength); // This is the output of the length
bin = ByteBuffer.allocate(packetLength); // This is where the error happens
}
int readSize = Math.min(packetLength, buffer.remaining());
buffer.limit(buffer.position() + readSize);
bin.put(buffer);
buffer.limit(bytesRead);
packetLength -= readSize;
if(packetLength == 0) {
bin.flip();
packets.add(bin);
}
}
byte[] remaining = new byte[buffer.remaining()];
for(int i = 0; buffer.remaining() > 0; i++) remaining[i] = buffer.get();
buffer.clear();
for(byte b : remaining) buffer.put(b);
}
このコードは、読み取りによって、一緒に送られた個々のパッケージを再構築しようとしますパケットサイズ(パッケージの最初のint)と同じくらい多くのバイトを単一のバッファにまとめます。
このエラーは、(少なくとも私はそれに遭遇したことはありません)
私は複数のクライアントを同時に処理しなければならず、他のすべてをブロックする可能性のある1人の人を待つのではなく、実際に要求を送信している人に反応したいからです。だから、同期が外れることはどういう意味ですか?私はこれを見ることができるいくつかの文書がありますか? – user3088126
私はあなたが長さの単語としてパケットの一部を読んでいることを意味します。と言いました。シンプルなコンセプトで、ドキュメントは必要ありません。 NIOをブロッキングモードで使用していますが、これはストリームを使用するのと同じです。そうでなければ、 'select()'ループの代わりにreadループを使うことで、ノンブロッキングモードでそれを悪用しています。どちらの方法でも、あなたのコメントに記載された目的を達成できない場合があります。クライアントのサービスを開始すると、他のすべてのクライアントが待機します。 – EJP
私はselectループを使用しますが、このコードセグメントにはありません。すべての着信パケットは他のスレッドで処理されるため、このパケットはブロックされません。 – user3088126