I want to use a SocketChannel and to have a timeout for its read/write methods. I've tried to set a timeout for the Socket that owns my SocketChannel like this:
channel.socket().setSoTimeout(TIMEOUT);
but that doesn't work. Is there any other solution?
According to this article, SocketChannel will not timeout for its read operation but you can get this effect from reading from the channel in another way.
SocketChannel socketChannel;
socketChannel.socket().setSocketTimeout(500);
InputStream inStream = socketChannel.socket().getInputStream();
ReadableByteChannel wrappedChannel = Channels.newChannel(inStream);
reading from the wrappedChannel will timeout according to the socketTimeOut you have set.
If you are familiar with using Java Selector, you can emulate socket timeout yourself using selector. It is helpful to see sun.nio.ch.SocketAdaptor.
It should be careful to use Thread.interrupt().
SocketChannel is InterruptibleChannel. As you read the description of InterruptibleChannel, Thread.interrupt() causes to close SocketChannel.
If you want to use SocketChannel after timeout, you cannot use the InterruptibleChannel feature.
You could also consider making your channel non-blockable and just using System.currentTimeMillis().
Related
I have a problem while the socket when it find a no route to host. It wait for quite a long. I want to change the connection timeout. The select(timeout) method of selector it's useless here. So i wanted to use channel.connect(address,timeout) as socket accept, but in API there is no such method. So i call the method from socket like: channel.socket().connect(address, timeout) but i get the following exception:
java.nio.channels.IllegalBlockingModeException.
How do i put timeout on connection in channels?
You can try :
while (! channel.finishConnect()) {
<... timer like Thread.sleep() ..>
}
I am writing ftp server in java using NIO non-blocking technology.
I want to prevent user from connect to my server and then do nothing.
Here is my code snippet:
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = serverChannel.accept();
socketChannel.socket().setSoTimeout(3000);
socketChannel.configureBlocking(false);
....................
It does not works. Um... is it possible to throw an exception when the user do nothing (e.g. say 15 minutes)?
thank you very much
socketChannel.socket().setSoTimeout(3000);
You've done it. But then you also put the channel into non-blocking mode, which prevents you getting timeout exceptions. If you're using non-blocking mode, and therefore presumably also select(), you have to manage the timeout yourself.
you can make a SocketChannel from a SocketAddress, but suppose you have a BluetoothSocket. How to make a SocketChannel?
No, but you can get a ReadableByteChannel and a WriteableByteChannel from its input and output streams via the Channels class.
I'm trying the Java.nio-package for non-blocking communication. So I got my ServerSocketChannel and all my connected clients (SocketChannel) in a Selector and wait for data (OP_ACCEPT/OP_READ) using Selector.select().
My question is: Can I - instead of using a ByteBuffer and read directly with SocketChannel.read() - use the underlying Socket, get an InputStream and read using that stream? Or will that mess up the selector-stuff?
You can't.
http://download.oracle.com/javase/1.4.2/docs/api/java/net/Socket.html#getInputStream%28%29
If this socket has an associated channel then the resulting input stream delegates all of its operations to the channel. If the channel is in non-blocking mode then the input stream's read operations will throw an IllegalBlockingModeException.
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.