Java TelnetClient が「続行するには任意のキーを押してください」でハングする
-
16-09-2019 - |
質問
Linux 上で実行される Java プログラムがあり、次を使用してリモート サーバーに Telnet 接続します。 org.apache.commons.net.telnet.TelnetClient
そしていくつかのコマンドを実行します。問題は、ユーザーに「続行するには任意のキーを押してください...」と要求する出力画面に到達したときに断続的にハングすることです。このプログラムは、実行する 10 回に 1 回程度、私が実行している 7 台のサーバーのうちの 1 回でこのプログラムがハングアップします。問題があるサーバーは 3 台のみです。また、同じプログラムを Windows ボックスで実行すると、常に動作します。
他にこのような問題に遭遇した人はいるだろうかと思ったのですが?
テストサーバーでは、テストするたびにハングする可能性があります。ハングを引き起こさない他のコマンドを送信しようとしましたが、うまくいきませんでした。キャリッジリターン、ラインフィード、文字の追加、ラインフィードの挿入をすべて試しました。クライアントを続行させるものは何もないようです。
言い忘れていましたが、私が最初に思いついたのはバッファのフラッシュでした。問題が解決する可能性があると思われる場所に、flush コマンドを置きました。
また、それを実行して書き込み行からの出力を観察すると、「任意のキーを押してください」が見つかり、続行しますが、ターミナルがハングして続行されないことにも言及します。
電話をかけるコード:
readUntil("X) Exit (no report)");
write("C", false);
out.flush();
readUntil("continue....");
// write this for all servers.
write("", true);
out.flush();
readUntil("X) Exit");
write("X", false);
/*
* This method is used to read the command line until the pattern that was
* passed in is found.
*/
public String readUntil(String pattern) throws Exception {
try {
String tempString;
char lastChar = pattern.charAt(pattern.length() - 1);
StringBuffer sb = new StringBuffer();
//boolean found = false;
char ch = (char) in.read();
while (true)
{
// NOTE: Turn line below on to watch the program perform the telnet
System.out.print(ch);
sb.append(ch);
tempString = sb.toString();
if (ch == lastChar) {
if (tempString.endsWith(pattern))
{
// log to file
logFileWriter.write(tempString);
logFileWriter.flush();
return tempString;
}
}
ch = (char) in.read();
}
}
catch (Exception e) {
e.printStackTrace();
throw e;
}
}
/*
* writes the String passed in to the command line.
* boolean userWriteln: true - use the return key after the command, false - just type the
* command with NO enter key
*/
public void write(String value, boolean useWriteln)
{
System.out.println("WRITTING '" + value + "'");
try {
if (useWriteln)
{
out.println(value);
}
else
{
out.print(value);
}
out.flush();
System.out.println(value);
}
catch (Exception e) {
e.printStackTrace();
}
}
スタックトレース:java.net.SocketTimeoutException:読み出しタイムアウト at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:129) at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) at java.io.BufferedInputStream.read(BufferedInputStream.java:237) at java.io.FilterInputStream.read(FilterInputStream.java:66) at java.io.PushbackInputStream.read(PushbackInputStream.java:122) at org.apache.commons.net.io.FromNetASCIIInputStream.__read(FromNetASCIIInputStream.java:77) at org.apache.commons.net.io.FromNetASCIIInputStream.read(FromNetASCIIInputStream.java:175) at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) at java.io.BufferedInputStream.read(BufferedInputStream.java:237) at org.apache.commons.net.telnet.TelnetInputStream.__read(TelnetInputStream.java:122) at org.apache.commons.net.telnet.TelnetInputStream.run(TelnetInputStream.java:564) at java.lang.Thread.run(Thread.java:619)
どこにかかるか:英語 1 6000 4462 26 % 13826 11056 20 %
Calls answered since Thu Jun 4, 2009 3:11 am: 41245
何かキーを押すと続行します....
解決
いくつかの理由が考えられます。
出力 (リモート コマンドの入力) をフラッシュしていないため、「任意のキー」が送信されることはありません。
プログラムはデータを送信しようとしますが、入力 (リモート コマンドの出力) は読み取られません。I/O は通常「同時に」発生し、十分なタイミングでもう一方を処理しないと一方がブロックされるため、これを 2 番目のスレッドで行う必要があることに注意してください。
おそらく、アプリが端末を「RAW モード」にするために問題が発生している可能性があります。しかし、出力をフラッシュするとそれが修正されるはずです:/