2012-01-06 14 views
1

私は単純なネットワーククライアントを作ろうとしています。クライアントはキュー(バッファ)に書き込むことができ、2番目のスレッドはこのバッファを取り、それをサーバに書き込む必要があります。バッファにチャネルが書き込まれている間にバッファを書き込もうとしています

java.nioで試したところ、ByteBufferThreadが作成されました。このByteBufferは、チャネルに書き込むためにThreadwhile(true)で使用されています。私はput()メソッドを使用して静的なバッファにいくつかのバイトを入れているいくつかの点で私のメインループでは

。デバッグモードで

Iは、チャネル書き込みスレッドを中断した後、私は(バッファに書き込むだけ押し込ま「A」)私のメインプログラムループを介してバッファを充填しました。

3回または4回ボタンを押した後、再びチャンネル書き込みスレッドを開始し、うまくいきました。

しかし、私は、メインループスレッドにバッファオーバーフローのエラーを取得していますプログラムは普通してみてください。私のプログラムはバッファが私のchannel-writing-threadによってアクセスされている間にバッファにデータを入れようとしていると思う。私は両方のスレッドの両方の部分でsynchronizedキーワードを使用しようとしましたが、それは役に立たなかった。

メインループ:

class PacketReader implements Runnable 
{ 
public static ByteBuffer writeBuffer = ByteBuffer.allocate(1024); 
[...] 
public void run() 
{ 
    while (true) { 
[...] 
     if (selKey.isValid() && selKey.isWritable()) 
     { 
      SocketChannel sChannel = (SocketChannel)selKey.channel(); 

      //synchronized (PacketReader.writeBuffer) 
      //{ 
       if(PacketReader.writeBuffer.hasRemaining()) 
       { 
        PacketReader.writeBuffer.flip(); 
        int numBytesWritten = sChannel.write(PacketReader.writeBuffer); 
        PacketReader.writeBuffer.flip(); 
       } 
      //} 
     } 
[...] 

任意のアイデアはどのようなバッファリングのライトシステムを作成するには: "PacketReader"(まあ、それは実際に読み書きです)という名前の

[...] 
    if(Gdx.app.getInput().isKeyPressed(Input.Keys.A) && (now.getTime() - lastPush.getTime()) > 1000) 
     { 
      lastPush = now; 
      //synchronized (PacketReader.writeBuffer) 
      //{ 
       PacketReader.writeBuffer.put(("KeKe").getBytes()); 
      //} 
} 
[...] 

マイスレッド?私はそれが一般的な問題だと思うが、私は何を検索するのか分からない。すべてのNIOチュートリアルでは、バッファがチャンネルループ内に埋め込まれていると思われるようです。

最後に、ネットワークコンポーネントが一度起動し、プログラム内でプログラムを作成しようとしていますが、キューの処理やキューを待たずにパケットを送信する静的送信メソッドを使用したかっただけです。

おそらくどこかにチュートリアルがありますか?への直接の答えではないほとんどのゲームは、同様の概念を使用する必要がありますが、私はNIO実装と任意のオープンソースのシンプルなJavaのゲームを見つけることができませんでした(私はフレームワークなしでそれをしようとしているので、私はアンドロイドのためにそれを使用します)

答えて

1

あなたの質問は、これを簡単にするために既存のNIOフレームワークを使用することを検討する必要があります。 NettyとGrizzlyは一般的な例です。私は個人的にNIOを使って自分のサーバーを最初から書くのではなく、Nettyを使います。

あなたはおそらくもネッティーが、私は彼らが彼らの実装を最適化していることを前提とするので、バッファへの書き込み/読み取りをどのように扱うかで見ることができます。

+0

この度はありがとうございます。私はKryonetやPyronetのようなlightwightフレームワークについて考えてきましたが、Androidでこれを使用しているので、私は直接的なプログラミングがパフォーマンスにとってより良いと思っていました。一方、私はNIOを学びたかったので、なぜ自分自身を拷問しないのですか? :D –

2

はあなたではなくあなたがチャネルに送出されているのと同じバッファに置くこと、書くためにバッファのキュー(たとえば、ConcurrentLinkedQueue)を維持してみてください可能性があります。

送信する何かをキューに入れる:チャネルが書き込み可能であるとき、あなたの選択のループで次に

ByteBuffer buff = /* get buffer to write in */; 
buff.put("KeKe".getBytes()); 
queue.add(buff); 

を:

for(ByteBuffer buff = queue.poll(); buff != null; buff = queue.poll()) { 
    sChannel.write(buff); 
    /* maybe recycle buff */ 
} 

あなたはまた、チャネル上の書き込み金利を設定/解除する必要があるかもしれませんキューが空であるかどうかによって異なります。

+0

ありがとうRussel :)私は私のアプリケーションのためにあなたの例を使用しました。私はまだあなたのソリューションに関するいくつかの質問があります:それは私が(パケットの送信ごとに)多くのバッファを作成しているという意味ではないでしょうか?それがAndroid搭載デバイスの問題を再発生させる可能性がありますか?あるいは、私はバイト[]配列をキューに入れ、ByteArrayOutputStream経由でバイト配列を作成することについて考えてきました。したがって、ここでの質問は:ByteArrayOutputStreamとByteBufferの違いは、Androidデバイスに最適ですか? –

0

NIOの要点は、別のスレッドを必要としないことです。充填を行っているスレッドも書き込みを行うべきです。

+0

申し訳ありませんが、私は完全にそれを理解していません。私は少しAndroidのゲームのためにこれを作っています - あなたによると、レンダリングスレッドに全体の塗りつぶしと書き物をする必要がありますか?グラフィックスとロジック部分の直前ですか?しかし、ソケットの送信や読み取りに時間がかかる場合はどうすればよいでしょうか?私はレンダリングを待たなければならないので、ゲームは遅くなるでしょう...そして、レンダリングに時間がかかりすぎると、読み込みバッファにオーバーフローする危険性がありますか?それとも悪いですか? –

+0

@ Thom-私はレンダリングスレッドについて何も言わなかった。 – EJP

関連する問題