This question already has answers here:
Timeout for SocketChannel doesn't work
(3 answers)
Closed 4 years ago.
What is the best way to set a timeout to close a NIO SocketChannel if there is no data is received for a certain period after the connection is established?
Either:
You are using a Selector, in which case you have a select timeout which you can play with, and if it goes off (select(timeout) returns zero) you close all the registered channels, or
You are using blocking mode, in which case you might think you should be able to call Socket.setSoTimeout() on the underlying socket (SocketChannel.socket()), and trap the SocketTimeoutException that is thrown when the timeout expires during read(), but you can't, because it isn't supported for sockets originating as channels, or
You are using non-blocking mode without a Selector, in which case you need to change to case (1).
So you either need to use case (1) or a java.net.Socket directly.
I was looking for the same recommendation and could not find it easily - sharing it here.
There is a nice handler for netty called: ReadTimeoutHandler.
One can use it like that
channel.pipeline().addLast(new ReadTimeoutHandler(readTimeout));
it will drop io.netty.handler.timeout.ReadTimeoutException when failed to see any data doing the defined read timeout.
Related
This question already has an answer here:
How can I set Socket write timout in java?
(1 answer)
Closed 5 years ago.
In java, Socket has a method setSoTimeout that can be used to specify the reading timeout, but there is no method to specify the writing timeout
When I searched google, a lot of responses like "use nio and selectors", it looks that SocketChannel provides the way to specify the writing timeout, I brief the code of this class, but I still didn't find out how to do it.
Could someone show some code or some guide? Thanks
One possible way to mitigate the lack of a timeout option on a write call is to simply just set the SO_SNDBUF size via Socket.setSendBuffer to something very high. This will allow subsequent calls for writing to avoid blocking unless the pipe to the remote side gets backed up. If possible, structure your protocol such that you wait for some sort of response to data already sent before sending more data. That way, you won't ever exceed the send buffer.
YMMV.
This question already has answers here:
TCP keep-alive to determine if client disconnected in netty
(4 answers)
Closed 6 years ago.
I'm using Java and Netty to connect to a Unity-Client through a TCP/IP connection.
Sometimes the connection can break and the Unity-guy proposed to send a ping (just a one byte message) every 5 seconds and if the time of reception of the last ping is higher than 30 seconds, the connection is lost.
Do I really need to mesure the time? Isn't it enough to trigger an exception if I try to send something through the socket? Is there a case where a write won't detect a connection loss?
I tagged it Netty since I am using it, but it probably is the same with a simple Socket connection.
I think the real answer is: you have to define for yourself how you want your application to behave.
What I mean is: there are many different problems that could occur to your connection. Writing data, and failing immediately when that doesn't work is just one option to handle that.
You can also envision continuous pinging; for example to detect when the other is just "temporarily" unavailable. In other words: you establish some sort of "heartbeat" monitoring; and thus you enable your application for a "wider range" of potential "reactions".
This question already has answers here:
Sockets: Discover port availability using Java
(10 answers)
Closed 7 years ago.
This question is about datagram socket not tcp sockets, so please review it first before thinking its duplicate Is there a way to check the port before creating a new DatagramSocket. When the port is in use for example by another instance the code below throws SocketException
socket = new DatagramSocket(4446);
I would like to have it checked before I create the DatagramSocket object. So that if it is not available I can increment it and check again untill it becomes available and then I create the Socket ?
No. Do not think that you can check all the circumstances that might cause something to fail and then be guaranteed that it will succeed. First, you'll never be able to reliably cover all the ways it can fail. Second, things can change after you test and before you operate. Instead, try to do it, and if you fail, handle the failure. If the socket construction throws an exception, then try a different port.
This question already has answers here:
How to detect a remote side socket close? [duplicate]
(4 answers)
Closed 9 years ago.
I've read several questions about this on stack overflow already, but none of them has provided me with an elegant solution.
I know that calling isConnected() and isClosed() on the Socket is useless because it returns the local connection state (if the server is connected - not if the client is connected, as I want).
I also can't simply call if(socket.getInputStream().read()==-1)* because that would only account for the end of the stream (EOS) being reached - i.e., the client didn't send a message recently. This doesn't at all indicate that the client has disconnected however.
I'm considering just having the client send a message to the server letting it know it's disconnecting just before it closes the socket, but I'm wondering if there's a simpler solution I'm missing - wanting to know the connection state of the remote socket is a fairly commonplace desire. Thanks.
*not to mention the fact that InputStream#read() is an abstract method, I'm using DataInputStream for data read methods (i.e. readInt(), readByte(), etc.)
I'm considering just having the client send a message to the server letting it know it's closing just before it closes the socket,
Why? It's pointless. You will read this message instead of getting -1 from read(). The latter is all you need. The extra read() in your post is certainly a bad idea, but the read that reads messages isn't. You need that, and you will get EOS from it. You don't need an extra message to tell you the same thing.
This question already has answers here:
How to fix java.net.SocketException: Broken pipe?
(10 answers)
Closed 3 years ago.
For some of my Java NIO connections, when I have a SocketChannel.write(ByteBuffer) call, it throws an IOException: "Broken pipe".
What causes a "broken pipe", and, more importantly, is it possible to recover from that state? If it cannot be recovered, it seems this would be a good sign that an irreversible problem has occurred and that I should simply close this socket connection. Is that a reasonable assumption? Is there ever a time when this IOException would occur while the socket connection is still being properly connected in the first place (rather than a working connection that failed at some point)?
On a side note, is it wise to always call SocketChannel.isConnected() before attempting a SocketChannel.write(), and if so, can I also assume that the connection is "broken" and should be closed if both SocketChannel.isConnected() and SocketChannel.isConnectionPending() are both false?
Thanks!
What causes a "broken pipe", and more importantly, is it possible to recover from that state?
It is caused by something causing the connection to close. (It is not your application that closed the connection: that would have resulted in a different exception.)
It is not possible to recover the connection. You need to open a new one.
If it cannot be recovered, it seems this would be a good sign that an irreversible problem has occurred and that I should simply close this socket connection. Is that a reasonable assumption?
Yes it is. Once you've received that exception, the socket won't ever work again. Closing it is is the only sensible thing to do.
Is there ever a time when this IOException would occur while the socket connection is still being properly connected in the first place (rather than a working connection that failed at some point)?
No. (Or at least, not without subverting proper behavior of the OS'es network stack, the JVM and/or your application.)
Is it wise to always call SocketChannel.isConnected() before attempting a SocketChannel.write() ...
In general, it is a bad idea to call r.isXYZ() before some call that uses the (external) resource r. There is a small chance that the state of the resource will change between the two calls. It is a better idea to do the action, catch the IOException (or whatever) resulting from the failed action and take whatever remedial action is required.
In this particular case, calling isConnected() is pointless. The method is defined to return true if the socket was connected at some point in the past. It does not tell you if the connection is still live. The only way to determine if the connection is still alive is to attempt to use it; e.g. do a read or write.
Broken pipe simply means that the connection has failed. It is reasonable to assume that this is unrecoverable, and to then perform any required cleanup actions (closing connections, etc). I don't believe that you would ever see this simply due to the connection not yet being complete.
If you are using non-blocking mode then the SocketChannel.connect method will return false, and you will need to use the isConnectionPending and finishConnect methods to insure that the connection is complete. I would generally code based upon the expectation that things will work, and then catch exceptions to detect failure, rather than relying on frequent calls to "isConnected".
Broken pipe means you wrote to a connection that is already closed by the other end.
isConnected() does not detect this condition. Only a write does.
is it wise to always call SocketChannel.isConnected() before attempting a SocketChannel.write()
It is pointless. The socket itself is connected. You connected it. What may not be connected is the connection itself, and you can only determine that by trying it.
You should assume the socket was closed on the other end. Wrap your code with a try catch block for IOException.
You can use isConnected() to determine if the SocketChannel is connected or not, but that might change before your write() invocation finishes. Try calling it in your catch block to see if in fact this is why you are getting the IOException.