2011-09-13 16 views
3

私はStackOverflowとGoogleを見ていて、私の問題の解決策を見つけることができなかったので、ここで私がやっていることがあります。InputStreamから読み込みをプログラムでキャンセルするにはどうすればよいですか?

コンソールアプリケーション用のサーバーがあり、ユーザーは任意のTelnetクライアントでサーバーに接続します。 ClientThreadは3つのスレッドを持つクライアントを処理しています.1つのスレッド(ClientThread)はClientへのすべてのプログラムアクセスを制御し、ClientThreadは入力を処理し、出力を送信する2つのスレッドを保持します。 ClienThreadはクライアントソケットを読み取り、入力を処理するProcessingThreadに入力があればそれを送り、ユーザが指示したアクションを実行します。出力スレッドは、送信が必要な出力のキューを管理し、起動するたびに送信します。ユーザーが接続を切断すると、接続が終了する前に出力「キュー」に残っているOutputを使用することがあります。そのため、出力キューが空になるまで接続が維持されるように設定する必要がありました。それ以上の出力がない場合は最終的に閉じます)が読み込み中にぶら下がっていて、それを閉じることができません。これはユーザーが切断すると、ソケットを閉じた直前には問題ではありませんでした。私はあなたに関連するコードを与えます。

public class ClientThread extends Thread { 
    // Initialization and other code not pertaining to the problem 

    public void run() { 
     while (connected) { 
     try { 
      String input = in.readLine(); 

      if (input != null) { 
       processor.queue(TextUtility.processBackspaceChars(input)); 
       timeoutTimer.interrupt(); 
      } 
     } catch (Exception e) { 
      if (e.getMessage() != null && !(e.getMessage().equals("socket closed"))) 
       server.appendError("Issue reading from client: " 
        + getClientDisplayInfo() + "\n" 
        + "&r-The issue is:&w- " + e.getMessage() + "&r-."); 
     } 
     } 

     while (disconnecting) { 
     try { 
      if (outputThread.hasOutput()) { 
       sleep(10); 

      } else { 
       disconnecting = false; 
       outputThread.disconnect(); 
       client.close(); 
      } 
     } catch (Exception exc) { 
      server.appendError("Failed to close the Thread for client: " + getClientDisplayInfo()); 
     } 
     } 
    } 

    public void disconnect() { 
     try { 
     connected = false; 
     disconnecting = true; 
     processor.disconnect(); 
     timeoutTimer.disconnect(); 
     in.close(); // This is the BufferedReader that reads the Socket Input Stream 
     this.interrupt(); // This was my attempt to break out of the read, but it failed 

     } catch (Exception e) { 
     server.appendError("Failed to close the Thread for client: " 
       + getClientDisplayInfo()); 
     } 
    } 
} 

私は出力を送信し続ける必要があるので、ソケットを閉じずにどのように読み込みをキャンセルできるか不思議です。

+0

Stackerのレスポンスは完璧に機能していましたが、それが持ち出されるにつれて、複数のクライアントに対応することはできませんでした。私はこのプログラムが今でもできるだけ効率的にしようとしている多数のクライアントをサポートするだろうとは思っていません。私が最終的に解決した解決策は、OutputThreadに 'disconnect'通知が送信されるとフラグが変更され、出力キューが空になるとクライアントにソケットを閉じるよう通知することです。これにより、出力キューをクリアするのに数秒かかる間、すべてが同じ方法で実行されます。 –

答えて

4

私が直面している問題に似ていると思いますyesterday入力ストリームでis.available()を呼び出し、(ブロッキング)読み込みを行う前にデータが利用可能かどうかを確認できます。

+0

ありがとう、これは魅力的に機能しました。私がこれを投稿した後、空になったときにSocketを閉じるようにクライアントに指示するフラグをOutputThreadに追加することができたことが分かりました。しかし、あなたのメソッドは完璧にも、答えのおかげで(私はソケットのAPIを参照する必要がありますGoogle/StackOverflowに加えて)のおかげで動作します。 –

+0

これには、新しいデータのストリームの連続的なポーリングが含まれます。これは、少数のクライアントに対してのみ機能します。これはまったく縮尺されません。通常はこれを行うことはありませんが、小さな、低負荷プログラムの場合、これはうまくいくでしょう。 – Jay

3

available()を呼び出さないでください:CPUをあまりにも頻繁に呼び出すことを無駄にするか、頻繁に呼び出して時間を浪費して応答時間に苦労します。 Socketで読み取りタイムアウトを設定し、読み取りスレッドが移動するたびに 'cancel'フラグをチェックさせます。あなたが設定したい場所からフラグを設定してください。

関連する問題