Windows XP と Windows 7 で Java アプリケーションを実行しています。このアプリケーションは、別のコンピュータへの TCP 接続を開いています。
XP マシンでネットワーク ケーブルを抜くと、-1 または SocketException が返されて、inputstream.read メソッドにほぼ即座に影響します。これは、ネットワーク接続の切断を検出する方法の 1 つです。Win7 マシンでは、ネットワーク ケーブルが取り外されている場合、Windows 自体がタスク バーの接続アイコンでこれを通知しますが、私の Java アプリケーションはこれに関するヒントを取得しません。何事もなかったかのようにそのままです。
TCP は Windows 7 で異なる動作をしますか、それとも Windows7 はアプリケーションからこの情報を隠しますか?
package tcpconnectionlossdetectiontest;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
public class TcpListener extends Thread {
private int _portNo = 23456;
private boolean _done = false;
public static void main(String[] args) {
int port = 23456;
if (args.length > 0) {
int position = -1;
do {
String arg = args[++position].trim();
if (arg.equalsIgnoreCase("-p") || arg.equalsIgnoreCase("--PortNo")) {
String argParameter = args[++position].trim();
// e.g. store additional argument
try {
port = Integer.parseInt(argParameter);
} catch (NumberFormatException nfex) {
port = 23456;
}
System.out.println("Argument " + position + " (" + arg + ", " + argParameter + "): port number set to " + port);
} else {
System.out.println("Argument " + position + " (" + arg + ") unknown.");
}
}
while (position + 1 < args.length);
// Parsing command line arguments ready.
}
TcpListener listener = new TcpListener(port);
listener.start();
}
public TcpListener(int portNo) {
this._portNo = portNo;
}
public void run() {
Socket s = null;
InputStream is = null;
byte[] buf = new byte[1000];
int readResult = 0;
int maxOpen = 3;
int openCounter = 0;
try {
ServerSocket sSocket = new ServerSocket(this._portNo);
while (openCounter < maxOpen) {
if (s == null) {
try {
System.out.println("waiting for connection on port " + this._portNo);
sSocket.setSoTimeout(60000);
s = sSocket.accept();
if (s != null) {
System.out.println("got connection on port " + this._portNo);
openCounter++;
is = s.getInputStream();
}
} catch (SocketTimeoutException stex) {
System.out.println("no connection yet...");
}
}
if (s != null && is != null) {
readResult = is.read(buf, 0, 1000);
}
if (readResult == -1) {
readResult = 0;
System.out.println("connection broken...");
is=null;
if (s != null) {
s.close();
s=null;
}
} else if (readResult > 0) {
System.out.println("Data read: " + new String (buf,0,readResult));
}
}
} catch (IOException ioex) {
System.out.println("IO exception caught:");
ioex.printStackTrace();
}
this._done = true;
}
}
切断後約 5 秒後の Windows XP での結果は次のとおりです。
waiting for connection on port 23456
no connection yet...
waiting for connection on port 23456
got connection on port 23456
Data read: Here is a connection from win7 to xp...
Data read:
IO exception caught:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at tcpconnectionlossdetectiontest.TcpListener.run(TcpListener.java:73)
Process exited with exit code 0.
切断後の Windows 7 での結果: ... 何もありません。アプリケーションは、切断が検出されずに開いたままになります。
@edit 2013-02-01 09:54: jre6 と jre7 で発生します。
@edit 2013-02-01 10:59: 32 ビットおよび 64 ビット Java で発生します。Win7 ラップトップと通常の PC で発生します。
@edit 2013-02-01 12:40: コード例と結果が追加されました。
@edit 2031-02-06: インターネット上で何も見つけられず、誰もこれに対する解決策を持っていなかったので、アプリケーションにアクティブなピンポン メカニズムを追加しました。これで、最大 20 秒後に検出できます。接続が切断されていること。
@edit 2013-02-08: ステータスを確認する別の方法は「netsh interface ip show interfaces」ですが、コマンド ラインの結果は、ステータスを知る前に Java で解析する必要があります。たぶん、その情報を取得するためのより良い方法があります。