8

Looking at JDK 1.7 API. I cannot seem to be able to set a connection timeout on an AsynchonousSocketChannel.

Is there any way I can set up a connection timeout on such a channel?

Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
Joe Lin
  • 153
  • 1
  • 10
  • 1
    Timeouts are for blocking operations. This is an async operation. The question doesn't make sense. – user207421 Dec 24 '13 at 00:10
  • @EJP - it does from the perspective of not wanting to wait around forever for a socket to connect even when your operations are async. That said, It's tricky to do, even in C. You have to use `select()` with a timeout with the socket in non-blocking mode. I'd really have to dig to figure out how to do that with NIO2 - it may not even be possible given how that's all abstracted away from you. – Brian Roach Dec 24 '13 at 00:18
  • @Brian There is no 'waiting around forever'. The default connection timeout is around a minute, platform-dependent. I'm aware how to do it in blocking and non-blocking mode, thanks, and I agree with your statement in your answer below that you can't in async mode given the existing Java APIs. They should have provided a timeout parameter to the connect method so that the `CompletionHandler` could get called earlier (noting that whatever technique you use at whatever level, you can only decrease the connect timeout, not increase it). – user207421 Dec 24 '13 at 01:30
  • @EJP Sorry, I didn't mean to imply *you* didn't ... when I posted the comment that part was meant as a general statement for the OP / other readers, then I decided to answer the Q. Agree that they should have included it in the API. And to clarify "wait around forever" meaning the default timeout. – Brian Roach Dec 24 '13 at 01:38
  • @Brian I think what is missing from the NIO2 API is asynchronous selectors (`WSAAsyncSelect()` or `WSAEventSelect()`), which is how you would have to implement it in Winsock. Maybe they only exist in Winsock: I'm not familiar with the Unix async APIs. – user207421 Dec 24 '13 at 03:06
  • Yeah, I'm the opposite, have never worked in windows. – Brian Roach Dec 24 '13 at 03:44

1 Answers1

8

The answer is: you can't.

The first thing to understand is how a TCP connect works. The kernel is sending SYN packets, backing off the time between each retry. This can be tuned via kernel parameters. An article covering this in detail (for linux) can be found here

To give you an idea of what's involved to implement your own shorter timeout for a socket connect is to put the socket in nonblocking mode, throw it in a select() with a timeout, then use getsockopt() to see what happened. This StackOverflow answer shows how this works.

With NIO.2, the connection process is handled for you using threads that you don't have access to. Unfortunately there's no way to tell it you want a shorter timeout on connects; it just calls your completion handler / notifies the Future when the connection either succeeds of fails (including timing out).

You do have the option of calling get(timeout, unit) on the returned Future, then cancelling the Futureif it times out ... but that means if you want the connect to be async you have to add another layer of threading / callbacks and may as well just implement your own async thing with nio.

One last thing worth mentioning since you're looking at async network stuff is that Netty does give this to you (using Nio):

Bootstrap bootstrap = new Bootstrap()
            .group(new NioEventLoopGroup())
            .channel(NioSocketChannel.class)
            .remoteAddress(new InetSocketAddress(remoteAddress, port))
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectionTimeout);

ChannelFuture f = bootstrap.connect();

And you can register a listener with that ChannelFuture for a callback.

Community
  • 1
  • 1
Brian Roach
  • 76,169
  • 12
  • 136
  • 161
  • The problem is that when there is no server listening, `connect()` will wait for a whole 2 seconds before it fails with "connection refused", even if you are trying to connect to localhost, where it is immediately known whether a server is listening or not. So, if you have a test which checks the behavior of your client when there is no server listening, then this test will take a whole 2 seconds to execute, and there is nothing you can do about it. That's unacceptable. – Mike Nakis Jul 09 '22 at 11:20