- PR -

PCの時刻を進めるとSocketTimeoutException

1
投稿者投稿内容
happity
会議室デビュー日: 2003/08/26
投稿数: 2
お住まい・勤務地: 福岡
投稿日時: 2004-12-17 15:03
ServerSocketを開いて待ちうけ、accept()したらひたすらsleep()する
単純なプログラムを、linux上(何でもいいですが)で起動し、
そのポートに対してSocket接続し、指定したタイムアウト値を
setSoTimeout()で設定するプログラムを、Windows XP SP2(j2sdk 1.4.2_06)
上から起動します。
Socket接続後、1分くらい、サーバ、クライアント共にだんまりになるような
感じにします。その状態で、クライアントPCのWindowsの「日付と時刻」を開き、
時刻を進めると、即、上記プログラムが、SocketTimeoutExceptionになって
しまいます。
これはWinXPのJVMの仕様なのでしょうか?
どなたかご存知の方がいらっしゃいましたらご教授ください。

サーバ起動イメージ
% java socktest_sv 20000 100

サーバプログラム(socktest_sv.java)
import java.util.*;
import java.io.*;
import java.net.*;

public class socktest_sv {
public static int port = 0;
public static int timeout = 0;
public socktest_sv(){
}
public static void main(String[] args){
if(args.length != 2){
System.out.println("USAGE : java socktest_sv port timeout(s)");
System.exit(1);
}
try{
port = Integer.parseInt(args[0]);
timeout = Integer.parseInt(args[1]);
ServerSocket server = null;
server = new ServerSocket(port);
while (true){
Socket soc = server.accept();
System.out.println(port + " accept");
System.out.println("sleep " + timeout + " seconds");
for(int i=0 ; i<timeout ; i++){
Thread.sleep(1000);
System.out.print("#");
}
BufferedReader in =
new BufferedReader(new InputStreamReader(soc.getInputStream()));
String tmp;
tmp=in.readLine();
System.out.println(tmp);
PrintWriter out = new PrintWriter(soc.getOutputStream());
out.print(new StringBuffer("OK").append(System.getProperty("line.separator")).toString());
out.flush();
}
}catch(Exception e){
e.printStackTrace();
}

}

}

クライアント起動イメージ
% java socktest_cl 192.168.1.1 20000 60000

クライアントプログラム(socktest_cl.java)
import java.util.*;
import java.io.*;
import java.net.*;

public class socktest_cl {
private static String host = null;
private static int port = 0;
private static int timeout = 0;
private static Socket client = null;
private static OutputStream out = null;
// private static InputStream in = null;
private static BufferedReader in = null;
public static void main(String[] args){
if(args.length != 3){
System.out.println("USAGE : java socktest_cl <host> <port> <timeout(ms)>");
System.exit(1);
}
try{
host = args[0];
port = Integer.parseInt(args[1]);
timeout = Integer.parseInt(args[2]);
String aa =
new StringBuffer("message")
.append(System.getProperty("line.separator")).toString();
exec(aa);
}
catch(Exception e){
e.printStackTrace();
}
}

private static void exec(String mess){
byte[] sendBuf;
byte[] recvBuf = new byte[2];
try{
client = new Socket(host, port);
client.setSoTimeout(timeout);
out = client.getOutputStream();
sendBuf = mess.getBytes("UTF-8");
out.write(sendBuf);
out.flush();
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String tmp;
tmp=in.readLine();
System.out.println(tmp);
}
catch(Exception e){
e.printStackTrace();
}
finally{
try{
out.close(); out = null;
in.close(); in = null;
client.close(); client = null;
}
catch(Exception e){}
}
}

}

時刻変更後の例外メッセージ
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder$CharsetSD.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder$CharsetSD.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at socktest_cl.exec(socktest_cl.java:52)
at socktest_cl.main(socktest_cl.java:27)
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-12-17 16:25
システムの時刻が進めば JVM からしてみれば時間が進んだのと同じですから即座にタイムアウトするのは正常な動作ではないでしょうか。
happity
会議室デビュー日: 2003/08/26
投稿数: 2
お住まい・勤務地: 福岡
投稿日時: 2004-12-17 16:52
試しに、サーバとクライアントを入れ替え、Linux側をクライアントとすると、
setSoTimeout()が設定された時点から相対的なタイマを持ち、設定した時間
が経過してはじめてタイムアウトになるようです。
(時刻を変更しても関係なく)
私としては、この方が納得できる動きです。

プラットフォームによってJVMの動きが違うのは困りものですね…。
1

スキルアップ/キャリアアップ(JOB@IT)