How do I create a TCP socket in Java?
How do I create such a TCP connection that it terminates only when I tell it to otherwise it remains open?
How do I use keepalives to know whether the server or client is still available?
Please Help!
How do I create a TCP socket in Java?
Socket socket = new Socket(hostname, port);
http://docs.oracle.com/javase/tutorial/networking/sockets/index.html
How do I create such a TCP connection that it terminates only when I tell it to otherwise it remains open?
They will remain open until either you or the other end closes it.
How do I use keepalives to know whether the server or client is still available?
That is up to you. You can send different messages, one of which is a heartbeat which tells the other end you are alive.
A common thing to do if you are sending binary messages is to send the length as an unsigned short or int value. I use a message of "length" 0 as a heartbeat.
The class java.net.Socket is what you are searching for.
Related
I have a java application which manages several socket connections to devices. I have no control over the protocol which these devices implement, and now I want my java application to send heartbeats for each device. The devices do not send data, but only respond to commands.
The javadoc for InputStream.read() states that if the end of stream is reached, it will return -1. So that seems like a reasonable way to check if the connection is open. But when I implement this solution, there are no bytes available (since the device only responds to commands), and since the connection is open, it will hang at the read call forever. Example, I peek at one byte and if that would be -1 the heartbeat would be "unhealthy":
public static void main(final String[] args) throws IOException {
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress("192.168.30.99", 25901), 1000);
System.out.println("Connected");
final BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
bis.mark(1);
System.out.println(bis.read()); // Stalls forever here
bis.reset();
System.out.println("Done");
}
}
Is it reasonable to say that, if no byte is received within x milliseconds, the device is connected?
Is there any surefire way to check socket connectivity without heartbeats where the ip and port is important?
Is there any surefire way to check socket connectivity without
heartbeats where the ip and port is important?
No, you can't reliably know if the other end is alive unless you try to communicate with it.
If the other end doesn't have a no-op ping function, you're pretty much out of luck. Waiting in a blocking read() call won't help you if the connection gets cut off.
Is it reasonable to say that, if no byte is received within x
milliseconds, the device is connected?
No. It means that the device hasn't sent anything in x milliseconds. Which is normal, as it only responds to commands.
when the other end of socket do not write any byte and wait to read from socket first, blocking on read is the default behavior.
with no control over the protocol , little can be done.
it is reasonable to say, successful connect is a weaker heartbeat.
you don't have to wait for x miliseconds which makes no difference on such protocol
another tricky way , you can try to send a few bytes that most unlikely being a valid command,
for example the '\0' or '\n' ,
hoping that it will do no harm to the device and the device can close socket actively on such invalid command.
when the other end closes socket actively , read call on such socket should return -1
the better heartbeat way always have something to do with the protocol,
as the no-op ping command suggested by #Kayaman
Maybe TCP level keep-alive is solution for you:
You can turn it on by using command:
socket.setKeepAlive(true);
It sets SO_KEEPALIVE socket option. Quote from SocketOptions java-API:
When the keepalive option is set for a TCP socket and no data has been
exchanged across the socket in either direction for 2 hours (NOTE: the
actual value is implementation dependent), TCP automatically sends a
keepalive probe to the peer. This probe is a TCP segment to which the
peer must respond. One of three responses is expected: 1. The peer
responds with the expected ACK. The application is not notified (since
everything is OK). TCP will send another probe following another 2
hours of inactivity. 2. The peer responds with an RST, which tells the
local TCP that the peer host has crashed and rebooted. The socket is
closed. 3. There is no response from the peer. The socket is closed.
The purpose of this option is to detect if the peer host crashes.
Valid only for TCP socket: SocketImpl
You could also use SO_TIMEOUT by using:
socket.setSoTimeout(timeout);
Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
With this option set to a non-zero timeout, a read() call on the
InputStream associated with this Socket will block for only this
amount of time. If the timeout expires, a
java.net.SocketTimeoutException is raised, though the Socket is still
valid. The option must be enabled prior to entering the blocking
operation to have effect. The timeout must be > 0. A timeout of zero
is interpreted as an infinite timeout.
Call those right after connect() or accept() calls, before the program enters to
'no control of underlying protocl' -state.
This question already has answers here:
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 1 year ago.
I have a Java application that connects to a service using a socket. I always expect to receive something from that socket, and if it disconnects I need to reconnect. Reconnect works fine when I close/open socket from remote application side in normal way. But when the remote application is killed, my Java application does not detect that. I run the thread with:
if (socket.isConnected()) { /* code */ }
This function does not detect when the socket is killed. Why? How to detect that remote socket is killed?
Note: I must use java 1.4
UPD
I do reading from socket input stream acording loggic:
if (in.available()) {...}
This not detects socket is disconnected. Should I use in.read() even if no data available to detect closed socket?
The various isXXX() methods of Socket don't track the actual state, but what has been done to the socket. For example isConnected() will return true even after a socket has been closed, if it has been connected at some point.
The only way to detect if a Socket is still valid is to try to use it, i.e. read or write to it. If an exception is thrown, you need to clean up and reconnect.
This function does not detect when the socket is killed. Why?
These functions only tell you the current state of the Socket object: they don't actively test the line. isConnected() means 'have I ever connected?'.
How to detect that remote socket is killed?
You need to read a message from the connection with an appropriate timeout. If the connection is closed or lost you eventually get an IOException, or a timeout will be reached.
BTW To save error messages, I suggest you send a message indicating a graceful disconnect before closing. This way graceful disconnects can be treated differently to connection failures in term of logging.
I have an as3 serversocket, we are connecting to the this serversocket via java socket(an android app). The problem is that, when serversocket application force closed, i couldnt find the a way to understand that remote socket is closed or unreachable, except when trying to flush() a message to that socket throws broken pipe error. The reason that i want to solve this problem in another way is not to make server application busy with connection check messages ?
A TCP connection is not a continuous flow like a river. It's a sequence of segments sent at discrete times - thus is more like cars on a road. So there is no way to be notified if the road is broken, until a car tries to reach the other end, fails, and calls you back.
You should simply keep sending cars at reasonable intervals (30 seconds?), thus instructing your server to do nothing when it receives a NOOP message (short for No Operation). The client will be programmed to start sending NOOP when the connection is idle (no message sent or received for 30 seconds), and when the driver calls back that he can't reach his destination, you close the current socket and attempt to create another one.
There are 3 ways for TCP to understand that connection has been closed:
One side got an error - it sends a Reset request to the other side to close the connection
One side actually wants to close the connection so it sends a FIN message to the other side
A time-out when trying to transmit something from one side to another. This time-out can only happen when a tcp-package is sent. After a connection has been made , tcp's packages are only sent on a data transmitting request (and connection closing request...).
So if one side disconnects suddenly, not in middle of data transmitting, there is no way of spotting a disconnection , but to send some package once a while.
You've found the only way. TCP doesn't provide any way of checking the state of a connection other than trying to use it. You can use this more intelligently, for example you can send yourself heartbeat messages and so forth. But there is no API that will tell you.
What you can do is let the server broadcast a I am alive message every 5/10 mins :)
I want to check when the internet goes off can i capture that event .I am not getting the proper API or any example which would explain the same .
I am using socket for (TCP)communication and I open a socket when the network is available. I have observed that the socket does not give any exception in case the network goes off.
If any one had done or any example links would be really helpful Thanks in advance
The problem is that no event 'network down' exists in tcp connections, they just go down.
As suggested by Jerome you should check if timeout is reached.
Of course if network goes down you won't receive packets neither be able to send them so the underlying InputStream and OutputStream will throw an IOException but just when they'll realize that network is not working properly (usually 2*rtt = 120 seconds, it depends how TCP layer is managed).
Look state diagram by yourself:
What typically happens is that when in ESTABLISHED your socket will send data over the socket while waiting for ACK from destination. ACK won't come since network went off so your socket's window fills up and socket starts resending packets until real timeout intervenes throwing the exception.
Another case is when network goes off and your socket realizes that it cannot write anymore on channel: it will throw an exception imediately upon calling outStream.write(...).
It's not that easy to tell whether the network is off or just slow.
If you set Timeouts, it will throw exception if it takes too long:
For sockets:
socket.setSoTimeout(CONNECTION_TIMEOUT);
For HttpURLConnections:
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setConnectTimeout(CONNECTION_TIMEOUT);
con.setReadTimeout(CONNECTION_TIMEOUT);
TCP is designed to be quiet when idle. There is no administrative packets on wire when there is no pending packet. If the connection is dead while idle, you will not know, no matter what the setting of the timeout is. It does have keepalives but it's pretty much useless at the recommended frequency of 2 hours and longer.
You need to build some heartbeat or keepalive in your application protocol to detect stale connections. Keepalive is nothing but a noop packet sent at regular interval to trigger TCP timeout when connection is down. In my app, I do this every 10 seconds.
Why don't you try pinging www.google.com
See http://java.sun.com/j2se/1.5.0/docs/guide/nio/example/Ping.java
My chat application connects to a server and information is sent/received by the user. When the connection changes, such as 3g->wifi, wifi->3g, losing a data connection, etc, the socket sometimes stays connected for ages before disconnecting. During this time, it's impossible to tell if the connection is still active, it seems as if messages are being sent just fine. Other times, when sending a message, it will throw an IO error and disconnect.
Apart from implementing code to detect connection changes and reconnecting appropriately, is it possible to have the socket immediately throw an IO exception when connectivity changes?
Edit: I'm connecting using the following code:
Socket sock = new Socket();
sock.connect(new InetSocketAddress(getAddress(), getPort())), getTimeout());
//get bufferedReader and read until BufferedReader#readLine() returns null
I'm not using setSoTimeout as data may not be transferred for long periods of time depending on the remote server's configuration.
Are you talking about a java.net.Socket connection? Then try setSoTimeout(). Otherwise specify how you're connecting.
This is an old problem that I've seen a few times before in the database world.
The solution I used there was to manage the connection at the application level. I'd explicitly send a no-op message of some sort (i.e. SELECT 1 WHERE FALSE) over the connection every so often as a ping, and if this failed I would tear down and re-establish the connection, possibly to a failover server if the original wasn't accepting connections.
As previous answers already pointed out, this is a common problem. Even after sending a custom "ping" it might need some time until the socket realizes that the underlying connection is broken. Plus, regular pings are quite energy-demanding using 3-4G mobile networks, due to their tail states. Don't do that!
What you can do, however, is requesting to get informed when the connectivity changes (last section), and close/reconnect the socket manually in the according broadcast receiver. (EDIT: I see you already found out about this; just keeping it here for completeness)