クライアントへのオープン接続用のセッション スレッドを使用してサーバーを作成しています。かなり単純です。バッファ付きリーダーを使用して入力から行を読み取るだけです。行が、ユーザーが終了したいことを示す特別な値に等しい場合、または null の場合、ループは終了します。それ以外の場合、メッセージはチェーンを介して、それを処理するためのモジュールに渡されます。テストの目的で、サーバーに telnet で接続し、コマンドを手動で入力するだけです。
端末ウィンドウを閉じるなど、QUITと入力する以外の方法で接続を終了しない限り、これで問題ありません。次に、未知の文字シーケンスを含むメッセージが生成され、不正な形式のメッセージがチェーンを通過します。この単純なテスト ケースでは、それほど重要ではありませんが、対処する必要がある問題を示しています。
私のコードは次のとおりです。
public void run () {
BufferedReader inReader;
UpstreamMessage message;
String lastLine;
Thread.currentThread ().setName ("UpstreamThread_" + outer.getId ());
try {
inReader = new BufferedReader (new InputStreamReader (outer.clientSocket.getInputStream (), "UTF8"));
while (!this.ending) {
// Read whatever was in the input buffer
lastLine = inReader.readLine ();
Logger.getLogger (this.getClass ().getName ()).log (Level.INFO, "Last data from input stream reader was \"{0}\"", lastLine);
if (null != lastLine && !lastLine.equals ("QUIT")) {
message = new UpstreamMessage (outer.sessionId, lastLine);
outer.server.acceptMessage (message);
} else {
// End the session
Logger.getLogger (this.getClass ().getName ()).log (Level.INFO, "Thread ending");
break;
}
}
} catch (IOException | IllegalArgumentException ex) {
Logger.getLogger (this.getClass ().getName ()).log (Level.SEVERE, ex.getMessage (), ex);
} catch (InterruptedException ex) {
// This is thrown when we're telling the thread to shut down so it's normal
Logger.getLogger (this.getClass ().getName ()).log (Level.INFO, ex.getMessage (), ex);
} finally {
this.terminate ();
}
}
ターミナル ウィンドウを閉じると、コンソールに次のログが出力されます。
2013 年 7 月 27 日 7:37:00 PM bikeshop.server.Session$UpstreamChannel 実行情報: 入力ストリーム リーダーからの最後のデータは " " でした
あるいは、lastMessage 変数が null を参照しているにもかかわらず、null チェックが失敗することを示唆する次のメッセージがロガーによって報告される場合もあります。
2013 年 7 月 27 日 7:37:00 PM bikeshop.server.Session$UpstreamChannel 実行情報: 入力ストリーム リーダーからの最後のデータは「null」でした
私は明らかに何か間違ったことをしているのですが、何が悪いのかわかりません。私のテスト 'if (null != lastLine && !lastLine.equals ("QUIT"))' は、端末を終了したときにバッファにあるものをキャッチしていません。このケースをより適切に処理するにはどうすればよいですか?
編集: ログと単一ステップのデバッグをより注意深く分析すると、telnet クライアントが終了時に一連の制御文字を送信することが明らかになりました。これはバッファから読み取られ、チェーンを通過して、プログラムの他の部分で警告をトリガーします。次に、セッションは再びループを通過し、現在閉じられているソケットからの読み取りを試みます。これは null を返し、ループは終了します。これが、クライアントから読み取られた最後の行が null であったかどうかについての混乱の原因です。最後に読み取られたものは実際には null でしたが、最後から 2 番目の読み取りが重要であり、異常な動作を引き起こしたものでした。
したがって、質問は、a) 終了時に telnet クライアントが送信する制御シーケンスは何か、または b) Java はその制御シーケンスをチェックする方法を知っているかのいずれかに変わったと思います。