How to terminate a server socket thread on timeout? - java

I'm using Spring Integration on the server side to offer a socket. The socket as a defined soTimeout, so that exceeding that timeout will close the current open socket connection to the client.
TcpConnectionFactoryFactoryBean fact = new TcpConnectionFactoryFactoryBean();
fact.setSoTimeout(timeout);
But the thread on the server side will continue. How can I force cancelation/termination of the server socket as well (maybe with an additional thread timeout, so that no thread can hang in the background by any issues)?

I presume you mean you want to stop listening for new connections when one of the client connenctions times out.
Implement ApplicationListener for TcpConnectionExceptionEvent and examine the exception; if it's a SocketTimeoutException, call close() on the server factory that was created by the factory bean.

Related

Java: Re-use ports before linux OS puts them into TIME_WAIT

I am trying to build a java multi threaded server using a thread pool. I have limited the number of threads to perform my actions to 15 but every time the server socket accepts a new connection it creates the connection on a new port, once the thread is complete it closes the socket however linux puts the port into a TIME_WAIT state. This server receives a lot of traffic and because of the wait it quickly runs out of available ports and hangs until the timed wait expires. I do not have root access to change the time wait time so is there a way to re-use ports instead of putting them into TIME_WAIT?
public static void main(String argv[]) throws Exception{
init_LogServer.initMarshal();
ServerSocket socket = new ServerSocket(44431);
ConcurrentHashMap<Integer, String> transactionMap = new ConcurrentHashMap<Integer,String>();
CountTrans Tracker = new CountTrans(transactionMap);
ExecutorService executor = Executors.newFixedThreadPool(15);
System.out.println("Waiting...");
//listen for log packets
while(true){
//open socket
Socket connectionSocket = socket.accept();
//send to thread
Runnable worker = new LogThread(connectionSocket, Tracker);
executor.execute(worker);
}
}
The way to stop TIME_WAITs piling up at the server is to be the one that receives the close first. That simply means that you should adjust your socket handling code to loop, instead of just processing a single request/response pair. When the client closes the socket, you will detect end of stream instead of a new request, close the socket, and exit the handler. Closing the socket after the client has already done so means that TIME_WAIT happens at the client end.
As another benefit, you can then implement connection-pooling at the client.
No, if you can't change the TIME_WAIT time you can't change the TIME_WAIT time.
If you could, you might run into problems because the idea of the TIME_WAIT state is to stop any stray packets from this connection from interfering with the next connection.
I suppose you'll have to get another IP address or make less connections.

time out for InetSocketAddress

I have the following code:
socket.connect(new InetSocketAddress(serverHost, serverPort), CONNECT_TIMEOUT);
The problem is that when the DNS is not accessible the InetSocketAddress takes 45sec to timeout and return an exception ("Host in not accessible...").
I need the entire command (so the creation of InetSocketAddress and the connect to timeout earlier. I did not find a way to make the new InetSocketAddress(serverHost, serverPort) timing out earlier.
Is it possible?
PS
I'm on Android but the problem is the same on other platform
There is no easy way. You need to run this code
socket.connect(new InetSocketAddress(serverHost, serverPort), CONNECT_TIMEOUT);
in a separate thread (i/o thread) and communicate with it from UI main thread. Once you are over your time limit - send it a terminate signal and proceeding in UI thread immediately, don't wait till it does terminate. Depending on the state, the i/o thread either dies immediately or eventually.

Waiting for ServerSocket accept() to put socket into "listen" mode

I need a simple client-server communication in order to implement unit-test.
My steps:
Create server thread
Wait for server thread to put server socket into listen mode ( serverSocket.accept() )
Create client
Make some request, verify responses
Basically, I have a problem with step #2. I can't find a way to signal me when server socket is put to "listen" state. An asynchronous call to "accept" will do in this case, but java doesn't support this (it seems to support only asynchronous channels and those are incompatible with "accept()" method according to documentation).
Of cause I can put a simple "sleep", but that is not really a solution for production code.
So, to summarize, I need to detect when ServerSocket has been put into listen mode without using sleeps and/or polling.
The socket is put into listening state as soon as you construct the ServerSocket object, not when you call accept. As long as you create the client after the ServerSocket constructor has completed, you won't have a problem. Connections will be accepted and internally queued until accept gets called.
Here is some code to demonstrate:
ServerSocket serverSocket = new ServerSocket(12345);
Thread.sleep(10000);
Socket socket = serverSocket.accept();
During that 10 second gap before accept is called, the OS netstat command will show the server socket in "LISTENING" state, and clients can connect to it. If a client connects during that 10 seconds, the connection is queued, and when the accept method is finally called it immediately returns the queued Socket object.
Why not to send single just before calling accept()?
connectionAccepted = true;
loc.notify();
socket.accept();
To be sure that the socket is ready add a tiny sleep in your "client" code:
wait();
// we are here when notify is called.
Thread.sleep(10); // 10 ms
startTest();
You can even do better: create loop that tries to "ping" the socket with a tiny sleep between attempts. In this case you will start test as quickly as it is possible.

java.net.SocketException Connection timed out error

I am getting below error when I am trying to connect to a TCP server. My programs tries to open around 300-400 connections using diffferent threads and this is happening during 250th thread. Each thread uses its own connection to send and receive data.
java.net.SocketException: Connection timed out:could be due to invalid address
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:372)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:233)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:220)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:385)
Here is the code I have that a thread uses to get socket:
socket = new Socket(my_hostName, my_port);
Is there any default limit on number of connections that a TCP server can have at one time? If not how to solve this type of problems?
You could be getting a connection timeout if the server has a ServerSocket bound to the port you are connecting to, but is not accepting the connection.
If it always happens with the 250th connection, maybe the server is set up to only accept 250 connections. Someone has to disconnect so you can connect. Or you can increase the timeout; instead of creating the socket like that, create the socket with the empty constructor and then use the connect() method:
Socket s = new Socket();
s.connect(new InetSocketAddress(my_hostName, my_port), 90000);
Default connection timeout is 30 seconds; the code above waits 90 seconds to connect, then throws the exception if the connection cannot be established.
You could also set a lower connection timeout and do something else when you catch that exception...
Why all the connections? Is this a test program? In which case be aware that opening large numbers of connections from a single client stresses the client in ways that aren't exercised by real systems with large numbers of different client hosts, so test results from that kind of client aren't all that valid. You could be running out of client ports, or some other client resource.
If it isn't a test program, same question. Why all the connections? You'd be better off running a connection pool and reusing a much smaller number of connections serially. The network only has so much bandwidth after all; dividing it by 400 isn't very useful.

java/groovy socket write timeout

I have a simple badly behaved server (written in Groovy)
ServerSocket ss = new ServerSocket(8889);
Socket s = ss.accept()
Thread.sleep(1000000)
And a client who I want to have timeout (since the server is not consuming it's input)
Socket s = new Socket("192.168.0.106", 8889)
s.setSoTimeout(100);
s.getOutputStream.write( new byte[1000000] );
However, this client blocks forever. How do I get the client to timeout?
THANKS!!
You could spawn the client in it's own thread and spin lock/wait(timeout long) on it to return. Possibly using a Future object to get the return value if the Socket is successful.
I do believe that the SO_TIMEOUT setting for a Socket only effects the read(..) calls from the socket, not the write.
You might try using a SocketChannel (rather then Stream) and spawn another thread that also has a handle to that Channel. The other thread can asynchronously close that channel after a certain timeout of it is blocked.
The socket timeout is at the TCP level, not at the application level. The source machine TCP is buffering the data to be sent and the target machine network stack is acknowledging the data received, so there's no timeout. Also, different TCP/IP implementations handle these timeouts differently. Take a look at what's going on on the wire with tcpdump (or wireshark if you are so unfortunate :) What you need is application level ACK, i.e. you need to define the protocol between client and the server. I can't comment on Java packages (you probably want to look at nio), but receive timeout on that ACK would usually be handled with poll/select.
There is no way to get the timeout, but you can always spawn a thread that closes the connection if the write hasn't finished.

Categories

Resources