Java - TCP exception - java

I have a TCP Server and Client both written in Java and running on separate machines on Rhel 5.3 with jdk1.6. I have handled pretty much all the methods i could find to detect a disconnection on the "Server".
Following is a snippet of the Server code
private void listenforConnection() {
try {
socket = serverSocket.accept();
socket.setTcpNoDelay(true);
socket.setKeepAlive(true);
socket.setSoTimeout(5);
bosTcpOutStream = new BufferedOutputStream(socket.getOutputStream());
bisTcpInStream = new BufferedInputStream(socket.getInputStream());
log("New connection accepted from " + socket.getRemoteSocketAddress().toString());
sendHeartBeatsToClient();
} catch (IOException ie) {
log("Listener IOException : " + ie.getMessage());
}
}
private void sendHeartBeatsToClient() {
try {
while (true) {
long lngCurrentMillis=System.currentTimeMillis() ;
if ((lngCurrentMillis - lngLastSentMessageTime) >= 5000) {
byte[] bHeartBeat = getHeartBeatMessage();
bosTcpOutStream.write(bHeartBeat);
bosTcpOutStream.flush();
lngLastSentMessageTime = System.currentTimeMillis();
log("Heartbeat sent.");
} else {
try {
if (bisTcpInStream.read() == -1) {
log("Read Input Stream returned -1");
break;
}
} catch (SocketTimeoutException se) {
//Do nothing as i am not expecting the client to send anything.
} catch (IOException e) {
log("Read Input Stream error - " + e.getMessage());
break;
}
}
Thread.sleep(1);
}
} catch (IOException e) {
disconnectClientAndCloseSocket();
log("IO Exception" +e.getMessage());
} catch (InterruptedException e) {
disconnectClientAndCloseSocket();
log("Thread interrupted terminating." + e.getMessage());
}
}
I have also modified the tcp-keepalive kernel parameters on the "Server" machine as below:
net.ipv4.tcp_keepalive_time=2
net.ipv4.tcp_keepalive_probes=1
net.ipv4.tcp_keepalive_intvl=2
Now when i am simulating a disconnection by unplugging the network cable of the Client machine(after it has established the connection and received the initial data from the Server), I am seeing two different outcomes which i am unable to understand:-
If i unplug the cable after 10 to 15 seconds of successful client connection. On the "Server" I receive an IO Exception with "no route to host" after 10 minutes of unplugging the cable.
If i unplug the cable after 60 or so seconds of successful client connection. On the "Server" an IO exception is thrown with "Connection timed out" within 10 seconds. This is valid behavior keeping in mind the keep alive settings.
I have tried this a couple of times and i always get the same result.
What i don't understand is why the first outcome takes 10 minutes and it doesn't behave like the second outcome. Am i missing something?

Related

Continuously connecting to a server via a Socket until a connection is established

I have a client that I want to try to continuously connect to a server until a connection is established (i.e. until I start the server).
clientSocket = new Socket();
while (!clientSocket.isConnected()) {
try {
clientSocket.connect(new InetSocketAddress(serverAddress, serverPort));
} catch (IOException e) {
e.printStackTrace();
}
// sleep prevents a billion SocketExceptions from being printed,
// and hopefully stops the server from thinking it's getting DOS'd
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
After the first attempt, I get a ConnectionException; expected, since there is nothing to connect to. After that, however, I start getting SocketException: Socket closed which doesn't make sense to me since clientSocket.isClosed() always returns false, before and after the connect() call.
How should I change my code to get the functionality I need?
You can't reconnect a Socket, even if the connect attempt failed. You have to close it and create a new one.

Java Sockets not connecting to most sites

I am writing a program that simply tests connections to ports on remote machines and checks if a connection was established or rejected, pretty much a port scanner. While it seems to work on localhost and some sites, for some reason it won't work on most IP addresses, when several of my classmates followed similar approaches and were able to probe these same sites. Some sites, such as wikipedia.org, will only go up to port 21 and then hang. Can anyone see any obvious problems with my code. Thansk in advance.
for(int i = 1; i <= maxPort; i++)
{
boolean found = true;
try
{
String[] hostNameArray = hostName.split(".");
socket = new Socket(hostName, i);
System.out.println("Test");
socket.close();
}
catch(java.net.ConnectException ex)
{
System.out.println("Error" + ex + "\t<"+i+">");
found = false;
}
catch(java.net.UnknownHostException ex)
{
System.out.println("Unknown host");
System.exit(-1);
}
catch(IOException ex)
{
System.out.println("IO Exception");
System.exit(-2);
}
if(found)
{
ports.add(i);
}
}
Places such as google.com will simply stop when I try to create the socket (i.e. the test statement is never printed) while wikipedia.org will simply hang after 21. Thanks again for the help.

Android client - Java server, Socket won't throw exception

I'm trying to connect my Android APP to a Java server that I've made for it.
I have a problem, the server works good and the APP works fine too when connected to the server.
The problem comes when I close the server and try to connect to it. The suppose is that the Socket.connect() would throw an exception that I would catch, but this exception is not thrown.
I don't know what I'm doing bad, I paste my code here for you to read and maybe somone can help me. Thanks for all mates :D
Connection attributes:
static Socket s;
static DataOutputStream output;
static boolean connected;
The method who needs the connection:
public void enviarDatos(int r, int g, int b){
connect();
if(connected){
panel.setText(panel.getText() + "\nEnviando datos...");
try {
output.writeUTF(r + "," + g + "," + b);
} catch (Exception e) {
panel.setText("Error: " + e.getMessage());
}
disconnect();
}
}
The methods to connect and disconnect are there:
public void connect(){
try {
s = new Socket();
int timeout = 1000;
s.connect(new InetSocketAddress(SERVER_ADDRESS, SERVER_PORT), timeout);
output = new DataOutputStream(s.getOutputStream());
connected = true;
panel.setText("Conexion exitosa.");
} catch (Exception e) {
connected = false;
panel.setText("Error: " + e.getMessage());
}
}
public void disconnect(){
try{
output.close();
s.close();
connected = false;
} catch(Exception e){
panel.setText("Error: " + e.getMessage());
}
}
The first connect() method is different from the one you posted in the large code block where you present both the methods. It's pretty unclear which one you are using to connect. Try adding the int timeout parameter to the connect() like this:
int timeout = 1000; // 1s timeout
s.connect(new InetSocketAddress(SERVER_ADDRESS, SERVER_PORT), timeout);
This should make connect throw an IOException after the timeout expires.
Hope this solves your problem.
I see one potential issue in "disconnect". I think you're trying to close the socket when the output stream is still opened. In this case, the socket may not close properly which may cause issues in reopening. Although you should see an exception being thrown during closing.
In disconnect(), can you try closing output first before closing the socket?
public void disconnect(){
try{
output.close();
s.close();
connected = false;
} catch(Exception e){
panel.setText("Error: " + e.getMessage());
}
}
I don't have the context of this problem, but that's one potential issue I saw. Hopefully it helps.

Socket connection doesn't time out

I'am trying to set a timeout when a client try to connect to a server, if the server is down, the connection will wait 10 sec befor throwing the timeout exception.
In my case the code bellow throw the IOException without waiting, I really don't get it !
public boolean establishConnection()
{
System.out.println ("Connecting to " +
this.getServerHostname() + " au port " + this.getServerPort()+ " ...");
try {
SocketAddress sockaddr= new InetSocketAddress(_serverHostname, _serverPort);
_echoSocket = new Socket();
_echoSocket.connect(sockaddr,10000);
return _echoSocket.isConnected();
} catch (UnknownHostException e) {
System.err.println("Unknown Host: " + this.getServerHostname());
return false;
} catch (SocketTimeoutException e) {
System.err.println("Timeout");
return false;
} catch (IOException e) {
System.err.println("IOException : " +
this.getServerHostname() + ":" + this.getServerPort());
return false;
}
}
You'll only get a timeout if your connection request is not answered. If the server immediately rejects it, or if the server doesn't exist, you'll get an exception immediately.
But is this what you want to achieve?
If your intention is, in case the server is temporarily down, then try again after 10 sec then your approach is wrong.
You should try to do a connection to the server and if you get an exception because the server is down, you can sleep for 10 seconds and try the request again.
Otherwise Ernest's answer is correct

I'm having troubles with Java sockets in a client/server type application when having to accept many connections

First of all, thanks for reading. This is my first time in stackoverflow as user, although I've always read it and found useful solutions :D. By the way, sorry if I'm not clear enough explaining myself, I know that my English isn't very good.
My socket based program is having a strange behaviour, and some performance issues. The client and server communicate with each other by reading/writing serialized objects into object input and output streams, in a multi-threaded way. Let me show you the code basics. I have simplified it to be more readable and a complete exception handling for example is intentionally ommited. The server works like this:
Server:
// (...)
public void serve() {
if (serverSocket == null) {
try {
serverSocket = (SSLServerSocket) SSLServerSocketFactory
.getDefault().createServerSocket(port);
serving = true;
System.out.println("Waiting for clients...");
while (serving) {
SSLSocket clientSocket = (SSLSocket) serverSocket.accept();
System.out.println("Client accepted.");
//LjServerThread class is below
new LjServerThread(clientSocket).start();
}
} catch (Exception e) {
// Exception handling code (...)
}
}
}
public void stop() {
serving = false;
serverSocket = null;
}
public boolean isServing() {
return serving;
}
LjServerThread class, one instance created per client:
private SSLSocket clientSocket;
private String IP;
private long startTime;
public LjServerThread(SSLSocket clientSocket) {
this.clientSocket = clientSocket;
startTime = System.currentTimeMillis();
this.IP = clientSocket.getInetAddress().getHostAddress();
}
public synchronized String getClientAddress() {
return IP;
}
#Override
public void run() {
ObjectInputStream in = null;
ObjectOutputStream out = null;
//This is my protocol handling object, and as you will see below,
//it works processing the object received and returning another as response.
LjProtocol protocol = new LjProtocol();
try {
try {
in = new ObjectInputStream(new BufferedInputStream(
clientSocket.getInputStream()));
out = new ObjectOutputStream(new BufferedOutputStream(
clientSocket.getOutputStream()));
out.flush();
} catch (Exception ex) {
// Exception handling code (...)
}
LjPacket output;
while (true) {
output = protocol.processMessage((LjPacket) in.readObject());
// When the object received is the finish mark,
// protocol.processMessage()object returns null.
if (output == null) {
break;
}
out.writeObject(output);
out.flush();
out.reset();
}
System.out.println("Client " + IP + " finished successfully.");
} catch (Exception ex) {
// Exception handling code (...)
} finally {
try {
out.close();
in.close();
clientSocket.close();
} catch (Exception ex) {
// Exception handling code (...)
} finally {
long stopTime = System.currentTimeMillis();
long runTime = stopTime - startTime;
System.out.println("Run time: " + runTime);
}
}
}
And, the client, is like this:
private SSLSocket socket;
#Override
public void run() {
LjProtocol protocol = new LjProtocol();
try {
socket = (SSLSocket) SSLSocketFactory.getDefault()
.createSocket(InetAddress.getByName("here-goes-hostIP"),
4444);
} catch (Exception ex) {
}
ObjectOutputStream out = null;
ObjectInputStream in = null;
try {
out = new ObjectOutputStream(new BufferedOutputStream(
socket.getOutputStream()));
out.flush();
in = new ObjectInputStream(new BufferedInputStream(
socket.getInputStream()));
LjPacket output;
// As the client is which starts the connection, it sends the first
//object.
out.writeObject(/* First object */);
out.flush();
while (true) {
output = protocol.processMessage((LjPacket) in.readObject());
out.writeObject(output);
out.flush();
out.reset();
}
} catch (EOFException ex) {
// If all goes OK, when server disconnects EOF should happen.
System.out.println("suceed!");
} catch (Exception ex) {
// (...)
} finally {
try {
// FIRST STRANGE BEHAVIOUR:
// I have to comment the "out.close()" line, else, Exception is
// thrown ALWAYS.
out.close();
in.close();
socket.close();
} catch (Exception ex) {
System.out.println("This shouldn't happen!");
}
}
}
}
Well, as you see, the LjServerThread class which handles accepted clients in the server side, measures the time it takes... Normally, it takes between 75 - 120 ms (where the x is the IP):
Client x finished successfully.
Run time: 82
Client x finished successfully.
Run time: 80
Client x finished successfully.
Run time: 112
Client x finished successfully.
Run time: 88
Client x finished successfully.
Run time: 90
Client x finished successfully.
Run time: 84
But suddenly, and with no predictable pattern (at least for me):
Client x finished successfully.
Run time: 15426
Sometimes reaches 25 seconds!
Ocasionally a small group of threads go a little slower but that doesn't worry me much:
Client x finished successfully.
Run time: 239
Client x finished successfully.
Run time: 243
Why is this happening? Is this perhaps because my server and my client are in the same machine, with the same IP? (To do this tests I execute the server and the client in the same machine, but they connect over internet, with my public IP).
This is how I test this, I make requests to the server like this in main():
for (int i = 0; i < 400; i++) {
try {
new LjClientThread().start();
Thread.sleep(100);
} catch (Exception ex) {
// (...)
}
}
If I do it in loop without "Thread.sleep(100)", I get some connection reset exceptions (7 or 8 connections resetted out of 400, more or less), but I think I understand why it happens: when serverSocket.accept() accepts a connection, a very small amount of time has to be spent to reach serverSocket.accept() again. During that time, the server cannot accept connections. Could it be because of that? If not, why? It would be rare 400 connections arriving to my server exactly at the same time, but it could happen. Without "Thread.sleep(100)", the timing issues are worse also.
Thanks in advance!
UPDATED:
How stupid, I tested it in localhost... and it doesn't give any problem! With and without "Thread.sleep(100)", doesn't matter, it works fine! Why! So, as I can see, my theory about why the connection reset is beeing thrown is not correct. This makes things even more strange! I hope somebody could help me... Thanks again! :)
UPDATED (2):
I have found sightly different behaviours in different operating systems. I usually develop in Linux, and the behaviour I explained was about what was happening in my Ubuntu 10.10. In Windows 7, when I pause 100ms between connections, all its fine, and all threads are lighting fast, no one takes more than 150ms or so (no slow connection issues!). This is not what is happening in Linux. However, when I remove the "Thread.sleep(100)", instead of only some of the connections getting the connection reset exception, all of them fail and throw the exception (in Linux only some of them, 6 or so out of 400 were failing).
Phew! I've just find out that not only the OS, the JVM enviroment has a little impact also! Not a big deal, but noteworthy. I was using OpenJDK in Linux, and now, with the Oracle JDK, I see that as I reduce the sleep time between connections, it starts failing earlier (with 50 ms OpenJDK works fine, no exceptions are thrown, but with Oracle's one quite a lot with 50ms sleep time, while with 100ms works fine).
The server socket has a queue that holds incoming connection attempts. A client will encounter a connection reset error if that queue is full. Without the Thread.sleep(100) statement, all of your clients are trying to connect relatively simultaneously, which results in some of them encountering the connection reset error.
Two points I think you may further consider researching. Sorry for a bit vague here but this is what I think.
1) Under-the-hood, at tcp level there are few platform dependent things control the amount of time it takes to send/receive data across a socket. The inconsistent delay could be because of the settings such as tcp_syn_retries. You may be interested to look at here http://www.frozentux.net/ipsysctl-tutorial/chunkyhtml/tcpvariables.html#AEN370
2)Your calculated execution time is not only the amount of time it took to complete the execution but includes the time until the finalization is done which is not guaranteed to happen immediately when an object is ready for finalization.

Categories

Resources