2012-03-12 20 views
8

私はServer-Clientアプリケーションを開発していますが、入力ストリームで入力データを待つことに問題があります。Java InputStreamはデータを待機します。

私は入力データの読み取り専用のスレッドを持っています。現在のところ、whileループは、データが利用可能になるまで保持します。 (N.B.プロトコルは以下の通りです:パケットのサイズを送信します、例えばNをintとして、次にNバイトを送ります)。

public void run(){ 
    //some initialization 
    InputStream inStream = sock.getInputStream(); 
    byte[] packetData; 
    //some more stuff 
    while(!interrupted){ 
     while(inStream.available()==0); 
     packetData = new byte[inStream.read()]; 
     while(inStream.available()<packetData.length); 
     inStream.read(packetData,0,packetData.length); 
     //send packet for procession in other thread 
    } 
} 

whileループでスレッドをブロックしますが、IMOは悪い考えです。私はThread.sleep(X)を使って、リソースがループで絶えず消費されるのを防ぐことができますが、確かに良い方法でなければなりません。

また、データの一部が遅延のあるサーバーによって送信されるため、スレッドをブロックするためにInputStream.readに依存することはできません。私は試しましたが、いつも予想外の動作に終わりました。

は私が任意のアイデアをいただければと思います:)

+2

InputStream.readは、すでにブロックのデータが入手できません。 'available'メソッドを破棄してください。 – UmNyobe

答えて

12

あなたは

DataInputStream in = new DataInputStream(sock.getInputStream()); 
//some more stuff 
while(!interrupted) { 
    // readInt allows lengths of up to 2 GB instead of limited to 127 bytes. 
    byte[] packetData = new byte[in.readInt()]; 
    in.readFully(packetData); 
    //send packet for procession in other thread 
} 

私は再利用可能なバッファをサポートしていNIOを遮断使用することを好む()DataInputStream.readFullyを使用することができます。

SocketChannel sc = 
ByteBuffer bb = ByteBuffer.allocateDirect(1024 *1024); // off heap memory. 

while(!Thread.currentThread.isInterrupted()) { 
    readLength(bb, 4); 
    int length = bb.getInt(0); 
    if (length > bb.capacity()) 
     bb = ByteBuffer.allocateDirect(length); 
    readLength(bb, length); 
    bb.flip(); 
    // process buffer. 
} 



static void readLength(ByteBuffer bb, int length) throws EOFException { 
    bb.clear(); 
    bb.limit(length); 
    while(bb.remaining() > 0 && sc.read(bb) > 0); 
    if (bb.remaining() > 0) throw new EOFException(); 
} 
+3

おそらく2GiBをあなたのメモリに読み込まないようにしています –

4

UmNyobeが言ったように、available()はあなたがは、デフォルトの動作をブロックしているようにブロックしたくない場合は使用されることを意味しています。

あなたのバッファにpacketData.lengthバイトを持っていたら、ただ、他のスレッドに処理するために利用可能であるものは何でも読むだけ送信パケットために、通常のreadを使用して...

+0

ありがとう...保存された1日。 – Velu