Java socket connection - how to set a timeout when connecting server restarts - java

I have a Java socket connection established with a server A. Server A randomly restarts during the day and my Java socket connection infinitely waits because it thinks that is receiving data.
I have set the soTimeout but it is only kicking in while read is still going on.
How do I set force a timeout on the socket connection? I want to break the socket connection after a set period of time.
Socket mySocket = new Socket(host, port) ;
mySocket.setKeepAlive(true);
mySocket.setSoTimeout(timeout);

You don't need to break the connection periodically. You may just use TCP Keepalive mechanism to send small "ping" requests in defined intervals. Whenever one of parties does not respond, TCP connection is closed. More info here: https://en.wikipedia.org/wiki/Keepalive

Related

Java Socket:why is there is no "write timeout" for the socket

There is the connecting timeout value passed to connect method, and there is the reading timeout set using setSoTimeout method. I was wondering why there is no method to set the "writing timeout"? I think there is the writing timeout concept in the TCP Protocol.
It wouldn't be much use.
In general TCP sending is asynchronous to the application. All that send() does is put the data into the socket send buffer. It then returns, while the send buffer is emptied to the network asynchronously. So there is nothing to timeout. And the absence of a timeout does not denote that the data has been sent to the peer.
send() blocks while the send buffer is full, and it would be possible to implement a timeout on that, and indeed you can do that yourself in non-blocking mode with select(), but the problem is that what timed out could be either the current send or a prior one. So delivering a timeout would be rather confusing. Instead what is delivered when all the TCP send timers time out internally is a connection reset.
I think there is the writing timeout concept in the TCP Protocol.
There is indeed, but that's at the level where TCP is asynchronously emptying the socket send buffer. It isn't under application control.
you can first try to connect...if connect fails catch exception
InetSocketAddress sockAdr = new InetSocketAddress(serveradres, 2222);
Socket newsok = new Socket();
int timeout = 2000;
newsok.connect(sockAdr, timeout);

Android socket connection issues

I am creating a chat application, which runs as a service. I connect to the chat server using a socket, and I declared a timeout using setSoTimeout.
When a connection is idle, (for example when I am at home and connected to WiFi) I never face issues. When I go outside, and my WiFi connection is lost, my phone switches to 3G. The problem is that the socket stays connected without receiving any data. (So the timeout exception isn't called.) < sometimes it connects after 30 mins, but this need to be reduced to at least a few seconds.
I also tried to add a CONNECTIVITY_CHANGE broadcast detector in my AndroidManifest.xml, this also didn't work.
See my socket connection below:
socket = new Socket(proxy);
SocketAddress socketAddress = new InetSocketAddress(HOST,
PORT);
socket.connect(socketAddress);
if (socket.isConnected()) {
socket.setSoTimeout(1020000); //Even when setting to 10000 makes no sense
return true;
} else {
Log.w("WARNING", "Failed to connect to the server");
return false;
}
In the background there are also some loops running which checks the server for chatmessages, these loops triggers a reconnect when no data is received, but this didn't work too. (During reconnect, I set the socket to socket.close() and socket = null before connecting again.)
So are there any ideas, maybe I need to use a different socket? Or some other code to resolve this problem? Thanks.
In such unexpected(as per application's perspective) network disconnection, the socket won't know it was disconnected. If this situation occurs, the only way is to try writing some data to the socket. When the socket is disconnected, writing data would throw IOExcpetion with message like Connection reset.
You'd better implement a heartbeat method to detect the disconnection. A packet sent to server every 5~10 seconds would detect network disconnection speedy enough.

setting timout for connection between server and client in java

My Server program waits for the Client for long time But I want the Server Socket to wait for the Client for only specified time limit, say 2 minutes.How can i set this time limit.I have used timeout on timeout on Server Socket which blocks the connection for the specified timeout Which is not desired.
You can use following method to set timeout in server socket : setSoTimeout(int timeout)
For more information read the documentation : ServerSocket

Something to know about socket and multithreading in java

I want to send a message to a socket on a gateway(client), and then wait for a message to recieve from a gateway.
While waiting, on other hand I again send a message from server socket to gateway which is client but on accept()(ServerSocket) method my connection blocks.
I was wondering is this because of the previous request which was waiting to recieve something by using inputStream. I used threads to maintain this and use setReuseAddress() to do this.
I am not posting a code right now as I just want to know is this logic is fine or is there any logic to handle multiple requests(messages) to be send from a Server-Socket to a client-Socket and I also dont want to close the socket because the socket has to be connected through out the application.
On the client end, you use a Socket object to connect to a server which uses a single ServerSocket. Once the connection is established you will have a Socket at both ends and you can use this Socket to Serversocket connection to send data in either direction. i.e.
A single server socket is needed for new connections only.
See: here

Should I close sockets from both ends?

I have the following problem. My client program monitor for availability of server in the local network (using Bonjour, but it does not rally mater). As soon as a server is "noticed" by the client application, the client tries to create a socket: Socket(serverIP,serverPort);.
At some point the client can loose the server (Bonjour says that server is not visible in the network anymore). So, the client decide to close the socket, because it is not valid anymore.
At some moment the server appears again. So, the client tries to create a new socket associated with this server. But! The server can refuse to create this socket since it (server) has already a socket associated with the client IP and client port. It happens because the socket was closed by the client, not by the server. Can it happen? And if it is the case, how this problem can be solved?
Well, I understand that it is unlikely that the client will try to connect to the server from the same port (client port), since client selects its ports randomly. But it still can happen (just by chance). Right?
Yes, close the socket, as soon as you detect a failure.
The socket will be "stuck" in "close_wait" if not closed properly.
Even if the socket is closed, it's state will be in time_wait for a short period.
However, if You design the application to use a different local port for each new connection, there is no need to wait for the old socket to be closed.
(As you are then creating a completly different socket, since a socket is identified by the remote-ip, remote port, local ip and local port.)
A quick/ dirty illustration of why this can't happen (note the client forcibly uses the same local port in its connection):
public class Server{
public static void main(String[] args) throws Exception {
new Thread(){
java.net.ServerSocket server = new java.net.ServerSocket(12345);
java.util.ArrayList<java.net.Socket> l = new java.util.ArrayList<java.net.Socket>();
public void run() {
try{
while(true){
java.net.Socket client = server.accept();
System.out.println("Connection Accepted: S: "+client.getLocalPort()+", C: "+client.getPort());
l.add(client);
}
}catch(Exception e){e.printStackTrace();}
}
}.start();
}
and a client (replace server address with something valid):
import java.net.InetAddress;
import java.net.Socket;
public class SocketTest {
public static void main(String[] args) throws Exception {
InetAddress server = InetAddress.getByName("192.168.0.256");
InetAddress localhost = InetAddress.getLocalHost();
Socket s = new Socket(server, 12345, localhost, 54321);
System.out.println("Client created socket");
s.close();
s = null;
System.gc();
System.gc();
Thread.sleep(1000);
s = new Socket(server, 12345, localhost, 54321);
System.out.println("Client created second socket");
s.close();
System.exit(55);
}
}
If you start the server and then try to run the client the first connection will succeed, but the second will fail with a "java.net.BindException: Address already in use: connect"
Short answer: yes, you should close socket on both ends.
Although the answer is simple, in reality it may be very hard to detect that the peer has stopped responding if you don't build some ACK/NACK scheme into your client-server protocol.
Even with your protocol ACKs your processing thread may be hanging waiting for ACKs that will never come from the client or vice versa.
If you use Blocking I/O, I would start by setting read timeouts on a socket. Unfortunately, if the peer becomes unresponsive, there is no corresponding time-out for the writes.
One blunt instrument that I found has value in our environment is to create blocking Sockets through java.nio methods and then interrupt the processing thread at configurable intervals.
Interrupting processing thread will close socket, but if you pick the timeout large enough you will know that there is a trouble. We chose this approach because application was written initially with blocking I/O and a cost to transition it to non-blocking was very high.
With the non-blocking I/O, though, you may check at a finer-grained interval the status of your connection and react more intelligently to the slow/unresponsive connections.
Though non-blocking I/O requires a higher upfront investment, I think it will pay better dividends in terms of reliability and better throughput later on.
the client operating system will not allocate the same port to a new socket so soon. there are several mechanism that prevents it. one of which is the TIME_WAIT state that reserves the port for some time after the connection is closed.
I wouldn't worry about it.
if you really need to detect disconnection you will have to implement ping/pong protocol, initiated by both the client and the server.
It sounds like your client is detecting loss of connectivity to the server (using Bonjour), but you don't have the corresponding capability in the other direction.
You're certainly going to want some kind of timeout for inactive connections on the server side as well, otherwise dead connections will hang around forever. Beyond the problem of potential IP address/port # collisions you mention, there's also the fact that the dead connections are consuming OS and application resources (such as open file descriptors)
Conversely, you might also want to consider not being too aggressive in closing a connection from the client side when Bonjour says the service is no longer visible. If you're in a wireless scenario, a transient loss of connectivity isn't that uncommon, and it's possible for a TCP connection to remain open and valid after connectivity is restored (assuming the client still has the same IP address). The optimum strategy depends on what kind of connection you're talking about. If it's a relatively stateless connection where the cost of discarding the connection and retrying is low (like HTTP), then it makes sense to toss the connection at the first sign of trouble. But if it's a long-lived connection with significant user state (like an SSH login session), it makes sense to try harder to keep the connection alive.
If you close server socket only in case of blocking socket then client socket will be closed but not vice versa.
otherwise it would be better socket in both end. Because socket is a heavy weigt for you system. It will use a local port and a remote port of your system forever.
Thanks
Sunil Kumar Sahoo

Categories