wierd behavior of setSoTimeout(int) on linux machine.... Bug?
I have come across a wierd behavior of setSoTimeout(int) for a socket on linux machine. The issue is that if you call setSoTimeout(int) for a socket (on linux machine) and after reading some data from input stream you want to disable the timeout by saying setSoTimeout(0) over the same socket then although the getSoTimeout() will return 0 but the actually the timeout value which was first set remains active through the session of the socket. The timeout is never disabled even if you call setSoTimeout(0). Is it a bug?
Can anyone suggest me a workaround to disable timeouts which are set over the sockets on linux system. This is the issue only on the linux machines. On windows machine subsequent call to setSoTimeout(0) disables the timeout. Workaround please.
Regards.
[793 byte] By [
crack_ita] at [2007-10-3 1:26:46]

after some testing i realized that it has nothing to do with the timeout value. Even if I dont set the timeout at all (i.e. I dont call setSoTimeout(int) even once) then also the communication is being messed up. If I dont send any data for some 34 secs then the socket hangs and any subsequent data sent over the socket reaches nowhere. After a couple of mins exception is thrown saying 'Socket closed'. The server is on linux and client on win2k machine. Can someone please throw some light on why it could be happening....... I have build 1.4.2_05-b04 installed on linux machine .. do I need to install some other build/version of java ?
Complete stack trace of execption on client side is
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.ObjectInputStream$PeekInputStream.peek(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.peek(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Sourc
e)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at ServerBehaviorTest.main(ServerBehaviorTest.java:33)
For reference client side code is :
try
{
Socket s=new Socket(args[0], Integer.parseInt(args[1]));
//Thread.sleep(10000);
ObjectOutputStream oout=new ObjectOutputStream(s.getOutputStream());
ObjectInputStream oin=new ObjectInputStream(s.getInputStream());
oout.writeObject("Hello");
oout.flush();
System.out.println(oin.readObject());
int i=1;
int timeout=Integer.parseInt(args[2]);
while (true)
{
oout.writeObject("Object "+i);
oout.flush();
System.out.println("Written");
i++;
System.out.println(oin.readObject());
System.out.println("Read");
Thread.sleep(timeout);
}
}
catch(Exception e)
{
e.printStackTrace();
}
and server side code is :
public void run()
{
try
{
//s.setSoTimeout(40000);//40 secs
//s.setSoTimeout(0);//disable explicitly
ObjectOutputStream oout=new ObjectOutputStream(s.getOutputStream());
ObjectInputStream oin=new ObjectInputStream(s.getInputStream());
//System.out.println("Inteaddress = "+s.getInetAddress().getHostAddress());
Object read=oin.readObject();
//s.setSoTimeout(0);
oout.writeObject("First Read Over : "+read.toString()+". Also now updated timeout value is "+s.getSoTimeout());
while ((read=oin.readObject())!=null)
{
oout.writeObject(read);
oout.flush();
}
}
catch(Exception e)
{
//e.printStackTrace();
}
any suggestions ..... ?
>
> any suggestions ..... ?
To me the behavior would suggest that you are using an incorrect message.
The server expects something and you are not sending exactly what it expects.
Are you using the same version of java on both ends?
Myself I never send data via sockets. I send messages that contain data. That way I can explicitly define what is being sent and more importantly I can explicitly define the completion of the message.
i am sending what the server is expecting. The server is a simple server which sends back to the client whatever it receives from it. I am sending the complete server and client code. I am not using the same version of jdk on both machines but that should not make any difference.
client code is:
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
public class ServerBehaviorTest
{
public static void main(String args[])
{
if (args.length!=3)
{
System.out.println("Usage : java ServerBehaviorTest <ip> <port> <senddelay_in_millisecs>");
return;
}
try
{
Socket s=new Socket(args[0], Integer.parseInt(args[1]));
//Thread.sleep(10000);
ObjectOutputStream oout=new ObjectOutputStream(s.getOutputStream());
ObjectInputStream oin=new ObjectInputStream(s.getInputStream());
oout.writeObject("Hello");
oout.flush();
System.out.println(oin.readObject());
int i=1;
int senddelay=Integer.parseInt(args[2]);
while (true)
{
oout.writeObject("Object "+i);
oout.flush();
System.out.println("Written");
i++;
System.out.println(oin.readObject());
System.out.println("Read");
Thread.sleep(senddelay);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
and server code is:
import java.io.*;
import java.net.*;
import java.util.Vector;
public class TimeoutServer implements Runnable
{
private Thread thread;
private ServerSocket server_socket;
private Socket s;
private Vector connected=new Vector();
TimeoutServer(int port) throws Exception
{
//System.out.println("1 , Server started.Waiting for client requests...");
server_socket=new ServerSocket(port);
thread=new Thread(this);
}
public void start()
{
thread.start();
}
public void shutdown()
{
try
{
if(server_socket != null)
server_socket.close();
for (int i=0; i<connected.size(); i++)
{
((ClientServer) connected.elementAt(i)).shutdown();
}
}
catch(Exception e)
{
}
connected.clear();
server_socket = null;
}
public void run()
{
while(server_socket!=null)
{
try
{
s=server_socket.accept();
ClientServer cs=new ClientServer(s);
connected.addElement(cs);
cs.start();
}
catch(Exception e)
{
//e.printStackTrace();
}
}
}
public static void main(String args[]) throws Exception
{
int port=9876;
if (args.length>0)
{
try
{
port=Integer.parseInt(args[0]);
}
catch(NumberFormatException e)
{
}
}
TimeoutServer tos=new TimeoutServer(port);
tos.start();
}
}
class ClientServer implements Runnable
{
private Thread thread;
private Socket s;
ClientServer(Socket s)
{
this.s=s;
this.thread=new Thread(this);
}
public void start()
{
thread.start();
}
public void shutdown()
{
try
{
if (s!=null)
s.close();
}
catch(Exception e)
{
}
}
public void run()
{
try
{
//s.setSoTimeout(40000);//40 secs
s.setSoTimeout(0);//disable explicitly
ObjectOutputStream oout=new ObjectOutputStream(s.getOutputStream());
ObjectInputStream oin=new ObjectInputStream(s.getInputStream());
//System.out.println("Inteaddress = "+s.getInetAddress().getHostAddress());
Object read=oin.readObject();
//s.setSoTimeout(0);
oout.writeObject("First Read Over : "+read.toString()+". Also now updated timeout value is "+s.getSoTimeout());
while ((read=oin.readObject())!=null)
{
oout.writeObject(read);
oout.flush();
}
}
catch(Exception e)
{
//e.printStackTrace();
}
//System.out.println("Thread terminated");
}
}
compile these codes and run the server on linux machine with build 1.4.2_05-b04 as I am testing it with this build and client on windows machine with any version/buil installed.
forgot to mention if you specify the value of last parameter less than say 30 secs (while running ServerBehaviorTest) the problem will not be there. If you specify the value greater than say 40secs then the problem will surface.
> i am sending what the server is expecting. The server
> is a simple server which sends back to the client
> whatever it receives from it. I am sending the
> complete server and client code. I am not using the
> same version of jdk on both machines but that should
> not make any difference.
It wouldn't make a difference if you were sending just data.
But you are sending objects, not data.
So I would suppose that that could make a difference.
You are getting an exception on the server which is causing it to close its accepted socket.
ejpa at 2007-7-14 18:24:18 >

the client and the server runs fine on windows machine without any exceptions. If I run the server on linux, the client just hangs and after sometime the socket gets closed. I am ready to simulate the problem by running the server on the linux machine on which I have tested this. You can connect to the machine by compiling and running the client i.e. ServerBehaviorTest and then see for yourself what exactly is happening. May be this will help you to come to some conclusion.
I will run the server from now onwards for 6 hours.
To run the client use java ServerBehaviorTest 66.197.155.53 9876 data_send_delay(in millisecs).
Please test with varying values of data send delay and you will see that if you specify this delay value to around 35000 (35 secs) then after sending the first two or three packets the client will not receive anything and simply be waiting for data. After sometime the socket will be closed. If however the delay value is less say 3000 (3 secs) then there will be no problem and the client will keep on running smoothly until you press CTRL+C to terminate it.
any insights?
> the client and the server runs fine on windows> machine without any exceptions. How do you know you are getting no exceptions? In the code you posted, ALL your exceptions are beings swallowed!
I am running the server with the printStackTrace() uncommented. In client also I am printing the stack traces so I know whether exception has occured or not.
Can you please try to connect to the test server which I am running for another 4 hrs. Please test with varying values of the data send delay and you will see for yourself the strange thing which is happening ... this is driving me crazy .......... :((
> the client and the server runs fine on windows
> machine without any exceptions. If I run the server
> on linux,...
And on windows you use the same version of java for the client and the server.
While when you run windows to linux the versions are different - right?
On windows machine I have tested with different verions as well as same version. When running server on linux I have tested with client using same as well as different versions on windows machine as is used by server on linux. Behavior is same. I don't think using different versions could be an issue. Please try to connect to the test server as is explained in the post # 7. May be it will help in tracing the problem.
When you get a connection reset from a write to a socket it generally means that the other end has already closed its socket.
ejpa at 2007-7-14 18:24:18 >

my concern is why at all the connection should get reset when the data send delay has values around 35 secs and not when the delay is less say 3 secs. Afterall I don't have any timeout value set over the socket...
I'll say it again. The other end has closed the socketOr there is some firewall product in the way and it is resetting connections for you .
ejpa at 2007-7-14 18:24:18 >

which firewall will close the socket if you send data after say 35 secs and will not do anything if you send data in intervals of 3 secs ? This is no firewall issue... Did you try to connect to the test server I had run? If not then I can again run it. That may help you come to some conclusion. Atleast I can't intepret anything from this weird behavior of linux or jdk. I am not even sure of what's causing the problem.....
Neither am I but if you think people here are going to connect to your server or execute your code I suspect you are very much mistaken.
ejpa at 2007-7-21 9:37:07 >

I gave the code for client as well as server. I started the server for your convenience only. If someone feels suspicious about connecting to the server then he can compile the client and server codes and deploy the server under some linux machine which is having build 1.4.2_05-b04 of jdk installed. This sounds to be much work that's why I started the server. I guess I have to install some other build of jdk on the linux machine and if that works then sun should document it as a bug and fix the reported build. Noone gets the duke then.
Message was edited by:
crack_it
> Noone gets the duke then.> :-( My children will now starve and I shall have to go around in bare feet just because you are too mean to award some dukes.
> was that funny?I thought it was mildly amusing.
> I gave the code for client as well as server. I
> started the server for your convenience only. If
> someone feels suspicious about connecting to the
> server then he can compile the client and server
> codes and deploy the server under some linux machine
> which is having build 1.4.2_05-b04 of jdk installed.
Someone could do that.
Not me though.
I get paid for that sort of thing.
Stuff I do here is free.
So it has to be very interesting before I would go to that level. And given that I never send 'objects' I doubt I would ever be that interested in it.