Close TCP connection after a minute of inactivity - java

I have a server that creates a new thread (client handler) every time a client connects to it. I want the client handler to close the connection if it has not received a DataInputstream message from the client in a minute.
I have tried:
if (System.currentTimeMillis() > startTime + 60000) {
System.out.println("Time up!!! for client: "+this.socket);
dos.writeUTF("close");
this.socket.close
break;
}
However, this only gets to the if statement after the client sends a message and I want to close the connection after 1 minute of inactivity from the client automatically.

There's multiple scenarios:
The timeout after the last read should be 60 seconds: Simply set the read() timeout: socket.setSoTimeout(60*1000); So if the reading thread has not received any data for a minute, the read() request will fail. Handle that exception accordingly, and you've got it.
The total connection timeout shall be 60 seconds, but the input still done in blockning mode: same as (1), but after each successful read you reduce the given timeout: socket.setSoTimeout(msLeft);
The total connection timeout shall be 60 seconds, but the input can be done in non-blocking mode: This uses is very different from those classes you use in your example, but here is a good guide to that: Non-blocking sockets.
However, I would stick to blocking I/O if possible, it's simply better for a lot of reasons.

Related

why did i get redis command timeout when using brpop comand whose timeout option value(50 seconds)is less than redis command timeout(200s) setting?

I'm using redis list as a distributed blocking queue. On the client side, I use the following code:
public String tryAquire(String appName, long timeout, TimeUnit timeUnit){
return String.valueOf(redisTemplate.opsForList.rightPop(getKey(appName), timeout, timeUnint));
}
It uses brpop command internal and the timeout value is set less than 50 seconds. This service works fine for about two weeks, until recent last 2 days I got a few exceptions of this:
org.springframework.QueryTimeoutException:Redis command time out;
nest exception is io.lettuce.core.RedisCommandException:
Command time out after 200 seconds(s)
This exception appears 1 or 2 times a day for about 2000 requests per day and after this exception the server still works fine and subsequent requests' cost time become normal, but the request which throws this exception would cost more than 200 seconds and that is a very bad case.
This time out value (200 seconds) fits my lettuce client side command timeout setting.
However, for the tryAquire(appName, timeout, timeUnit) method, the maximum blocking time is set less than 50 seconds. Thus this command should not cost time which is so much longer than 50s, because after 50 seconds if there is no elements in redis list it should just return null rather than keep waiting. It seems like there is no network issue for there is no socket related exception in log and after the redis command timeout exception the subsequent request is executed successfully.
Just in case someone encounteres the same problem. Long story short:The NAT mapping expires and the broken network link is awared of by the application after max tcp retries has been reached.
This service is deployed at a cloud environment which uses a customed SDN. The NAT mapping expires if there is no activity on a tcp connection for some time. However both tcp client and server can't be aware of that and the client would keep trying sending data even if the NAT mapping has expired, until some tcp retries max limit configuraion is reached.
A simple solution: Just set the redis server "tcp-keepalive" configuration value smaller than the NAT mapping expire time or use any other heartbeat mechanism if you don't want to change the redis server setting.

Stop Socket with timeout from waiting after data read from socket

I am trying to create a java http server using tcp sockets. HTTP 1.1 has a timeout value that will enable the connection to be persistent and wait for a short while for possible data from the client. I am trying to implement this timer in my program by using:clientSocket.setSoTimeout(). Even though this will help to leave the connection open for a certain amount of time, but it will wait for that exact amount of time before allowing the next request to be read.
For example:
If timeout is set to 5 seconds,
Request 1 is read. Then the socket hangs and wait until 5 seconds is over.
Request 2 is read. The socket waits until 5 seconds is up again.
This proves to be a problem if my timeout is set to big values. This should not be the case as the request should be processed once it is received and the timeout should only expire only if no data is received throughout the specified duration.
Can anyone advise me on how I could resolve this?
Edit:
For people who face a similar problem, here is my solution:
Since the client waits until the timeout before receiving all the data, I guessed that the client does not know that all the data from the server has been received. Hence, I added a content-length field to the HTTP response packet. Now, my client no longer hangs after receiving the data. The setSoTimeout does indeed work as stated!
Ok, when you receive a connection, then please start a new Thread like this:
class ClientService extends Thread {
private final Socket clientSocket;
public ClientService(Socket clientSocket) {
this.clientSocket=clientSocket;
}
public void run() {
// do your work with the Socket clientSocket here
}
}
this is how then your server code should look like:
while (true) {
Socket clientSocket = server.accept();
new ClientService(clientSocket).start();
}
It will allow you to process responses without waiting for one another till it timeouts.
HTTP 1.1 has a timeout value that will enable the connection to be persistent and wait for a short while for possible data from the client.
Not really. It has a connection: keep-alive setting, which is the default behaviour, and it allows endpoints to close connections that aren't in use after a period of idleness, but it doesn't have a timeout property itself.
I am trying to implement this timer in my program by using:clientSocket.setSoTimeout().
This has nothing whatsoever to do with HTTP. It is a socket read timeout.
Even though this will help to leave the connection open for a certain amount of time, but it will wait for that exact amount of time before allowing the next request to be read.
No it won't. It will cause read methods to throw SocketTimeoutException if no data arrives within the timeout period. Nothing else.
For example:
If timeout is set to 5 seconds,
Request 1 is read. Then the socket hangs and wait until 5 seconds is over.
No it doesn't.
Request 2 is read. The socket waits until 5 seconds is up again.
No it doesn't. You've made all this up. It is fantasy.
This proves to be a problem if my timeout is set to big values.
It isn't a problem with any timeout values whether large or small, because it simply does not happen.
This should not be the case as the request should be processed once it is received and the timeout should only expire only if no data is received throughout the specified duration.
That is exactly what Socket.setSoTimeout() already does.
Your question is founded on a fallacy.

SocketTimeoutException when ConnectTimeout and ReadTimeout is infinite? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Receiving request timeout even though connect timeout and read timeout is set to default (infinite)?
I tried to connect to a web service and received a SocketTimeoutException after approximately 20 seconds. The Tomcat server hosting the web service is down so the Exception is expected. However, I did not set the value of my ConnectTimeout and ReadTimeout. According to the documentation, the default values of these two are infinite.
One possibility for this is that the server I tried connecting to has its own timeout. But when my friend tried to connect to it using iOS, his connection timed out after approximately 1 minute and 15 seconds. If the server is the one issuing the timeout, our connection should have timed out at almost the same time. Please note that he is also using the default time out of iOS.
Why did my socket timed out so early when my connect and read timeout are set to infinite?
Is socket timeout different to connect and read timeout? If so, how is it different?
How can I know the value of my socket timeout? I am using HttpURLConnection.
Is there a way to set the socket timeout? How?
Below is a snippet of my code:
httpURLConnection = (HttpURLConnection) ((new URL("http://www.website.com/webservice")).openConnection());
httpURLConnection.setDoInput(isDoInput);
httpURLConnection.setDoOutput(isDoOutput);
httpURLConnection.setRequestMethod(method);
try
{
OutputStreamWriter writer = new OutputStreamWriter(httpURLConnection.getOutputStream());
writer.write("param1=value1");
writer.flush;
}catch(Exception e)
{
}
Why did my socket timed out so early when my connect and read timeout are set to infinite?
Code please.
Is socket timeout different to connect and read timeout? If so, how is it different?
SocketTimeoutException is a read timeout.
How can I know the value of my socket timeout? I am using HttpURLConnection.
HttpURLConnection.getReadTimeout(); also HttpURLConnection.getConnectTimeout().
Is there a way to set the socket timeout? How?
HttpURLConnection.setReadTimeout().
You have already cited all these methods in your original post. Why are you asking about them here?
Finally, I found what causing my timeout! It turns out that it is indeed the server who is causing my timeout. I doubt on this one at first because I am receiving a different timeout when using iOS which is more than 1 minute.
So here it is:
The operating system holding my Tomcat server is Windows. Windows' default number of retries for unanswered connection is 2. So when your first attempt to connect fails, you still have 2 retries left. The retries are all done internally. I'm not sure how the time for each retry is calculated but basically it's 3 + 6 + 12 = 21 seconds.
1st retry = 3 seconds
2nd retry = 6 seconds
3rd retry = 12 seconds
After the 3rd retry, your connection will be cut-off. Also, by that time, you already waited for 21 seconds.

Timer to check activity on socket connection?

We have a socket application which the snippet of the while loop is as below. What we would like to check is that say if it pass 30 seconds and no more data then shut the socket connection. At event if the some data is in then we reset the timer. Must I use the timer or system milliseconds
while ((readChar=readSocket.read()) != -1)
{
//processing.
}
You can configure the socket so that a read operation times out if no data is received within the specified interval.
From the Socket Javadoc:
public void setSoTimeout(int timeout) throws SocketException
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.
Parameters:
timeout - the specified timeout, in milliseconds.
Throws:
SocketException - if there is an error in the underlying protocol, such as a TCP error.
Since:
JDK 1.1
See Also:
getSoTimeout()
Using this approach, you can read data, consume it (however your need to), and then read from the socket again. If you get the timeout exception, then close the socket.
socket.setSoTimeout(30 * 1000); // timeout after 30 seconds
try
{
while ((readChar=readSocket.read()) != -1) // block reading data ...
{
// processing ...
}
}
catch (SocketTimeoutException e) // we didn't get any data within 30 seconds ...
{
socket.close(); // ... close the socket
}
Use asynchronous NIO operations.
If you use java6, async operations are tricky, but there are many network libraries (Mina, Netty) though they are rather heavy.
If you use java7, true async network operations are implemented and are easy to use (nio2). Even more easier is to use a lightweight nio2 library from https://github.com/rfqu/df4j.

How do you prevent a denial of service from exhausting a thread pool on a socket server in Java?

For work I have written a specialized HTTP server which only performs 301/302/Frame redirections for web sites. Recently, some nefarious clients have been intentionally opening sockets and writing one character every 500 milliseconds in order to defeat my TCP socket timeout. Then they keep the socket open indefinitely and have multiple clients doing the same thing in a distributed denial of service. This eventually exhausts the thread pool which handles the TCP connections. How would you write your code to make it less susceptible to this sort of bad behavior? Here's my socket accept code:
while (true) {
// Blocks while waiting for a new connection
log.debug("Blocking while waiting for a new connection.") ;
try {
Socket server = httpServer.accept() ;
// After receiving a new connection, set the SO_LINGER and SO_TIMEOUT options
server.setReuseAddress(true) ;
server.setSoTimeout(timeout) ;
server.setSoLinger(true, socketTimeout) ;
// Hand off the new socket connection to a worker thread
threadPool.execute(new Worker(cache, server, requests, geoIp)) ;
} catch (IOException e) {
log.error("Unable to accept socket connection.", e) ;
continue ;
}
}
timeout and socketTimeout are currently set to 500 milliseconds.
Start closing sockets after a certain time has passed. If a socket has stayed open too long just close it down. You could do this in two ways:
You could also put a time limit on how long the client takes to send you a request. If they don't sustain a certain level of throughput close em. That can be pretty easy to do in your read loop when your thread is reading the request by adding a System.currentTimeInMillis() at the start and compare to where you are as you loop. If it drifts past a certain limit they are shutdown and dropped.
An alternative idea to this idea is possibly not reject them but let your thread return to the pool, but put the socket on a stack to watch. Let the bytes pile up and after they reached a certain size you can them pass them to a thread in the pool to process. This the hybrid approach to cut em off vs. maybe they aren't bad but slow.
Another way to handle that is watch how long a thread has been working on a request, and if it's not finished within a time limit close the underlying socket. Then the thread will get a SocketException and it can shutdown and clean up.
Here are some other ideas that mostly involve using outside hardware like firewalls, load balancers, etc.
https://security.stackexchange.com/questions/114/what-techniques-do-advanced-firewalls-use-to-protect-againt-dos-ddos/792#792

Categories