Using non-blocking I/O, the code for connecting to a remote address looks something like:
SocketChannel channel = SelectorProvider.provider().openSocketChannel();
channel.configureBlocking(false);
channel.connect(address);
The connection process will then have to be finished by invoking finishConnect() on the channel when some selector says the corresponding key isConnectable().
Is there a way to specify the connection timeout when using this idiom?
Interesting question. I'm not sure that nio itself provides a solution.
In my experience, I've run a Callable to attempt the connection, and then used the Future to poll for a response, using 'interval' and 'timeout' variables to loop and Thread.sleep() for a response.
Hopefully that points you in a useful direction ...
Also, I suggest you take a look at Apache Mina (you could describe Mina as an nio framework). It handles a lot of this kind of stuff for you, for example in the StreamIoHandler http://mina.apache.org/report/trunk/apidocs/org/apache/mina/handler/stream/StreamIoHandler.html
The question doesn't really make sense. Timeouts are for blocking mode. If you want that, leave the channel in blocking mode and call channel.socket().connect(address, timeout);. If you want non-blocking mode, use your current code; then create a Selector; register the channel for OP_CONNECT; when you get it call finishConnect(), and if that returns true deregister OP_CONNECT and continue with the rest of your code.
Related
I have a question about a connect() call of a TCP socket implementation. What does it mean for a connect() call to be non-blocking. The connect() call does a three-way handshake with some other socket, by sending a syn, waiting for a SYNACK and then send an ACK. The connect() call also returns true if the connection succeeded or false if it did not succeed.
If the call is non-blocking then I guess that means that the connect should return immediately, even if it is still waiting for a SYNACK, but in that case it can never return false when it fails to connect because by then it already returned.
So my questions:
- What does it mean for a connect() call to be non-blocking.
- How does a connect() call achieve this? Is this only possible using threads?
- Im simulating a tcp stack in java, could you give a simplified example of how the non-blocking version would look? I included a sketch of what I think the blocking version roughly looks like (more psuedo code than actual java):
public boolean connect(IpAddress dst, int port){
// create a syn packet and send it
ipLayer.send(.....,<synpacket>);
try{
// wait for a synack and store it in receive_packet
ipLayer.receive(...., receivePacket,<timeout>);
} catch( TimeoutException e ){
// timed out.
return false;
}
// use information from a receivePacket to create an ack-packet then send it.
ipLayer.send(<ackpacket>);
return true;
}
So my questions: - What does it mean for a connect() call to be non-blocking.
Exactly what you said. It does not wait for network traffic.
How does a connect() call achieve this? Is this only possible using threads?
If you define threads broadly enough, then the answer is yes. But typically it's not implemented with what we normally consider threads. It just tells the network stack to make the connection. The network stack sends out packets and respond to things like timer and network interrupts to keep the process going.
Im simulating a tcp stack in java, could you give a simplified example of how the non-blocking version would look? I included a sketch of what I think the blocking version roughly looks like (more psuedo code than actual java):
Just don't wait for a reply. Determine if it's possible to send a SYN. If not, return an error. If so, send the SYN. If you need a thread to wait for the reply for some reason, then you'll have to create a thread to do that.
But something about your code is fundamentally broken. You either need a thread in both the non-blocking case and the blocking case or neither. It's impossible to need a thread in one and not the other. If you need a thread in the non-blocking case, it's only because you can't run your TCP engine without a thread. But then if you don't have one in the blocking case, there's no way to run your TCP engine. What happens when the other side sends packets? Say the other side sends a RST -- how will your code reply to it?
You need to look at the actual Java API. A non-blocking connect consists of two operations: a connect(), which sends the SYN and initiates the handshake, and a finishConnect(), which tests for completion of the handshake. The handshake is asynchronous, and when it completes it triggers an OP_CONNECT for the Selector.
There is no 'return false' from any connect operation in Java, but there are exceptions.
Java NIO offers SocketChannel and ServerSocketChannel which can be set to non-blocking mode (asynchronous). Most of the operations return a value that corresponds to success or that the operation is not yet done. What is the purpose of AynchronousSocketChannel and AsynchronousServerSocketChannel then, apart from the callback functionalities?
which can be set to non-blocking mode (asynchronous)
There's your misapprehension, right there. Non-blocking mode is different from asynchronous mode.
A non-blocking operation either transfers data or it doesn't. In either case there is no blocking, and the operation is complete once it returns. This mode is supported by SocketChannel, DatagramSocketChannel, and Selector.
An asynchronous operation starts when you call the method and continues in the background, with the result becoming available at a later time via a callback or a Future. This mode is supported by the AsynchronousSocketChannel etc classes you mention in your question.
The AynchronousSocketChannel and AsynchronousServerSocketChannel come into their own when using the methods that take a CompletionHandler.
For example the code in a server might look like this:
asynchronousServerSocketChannel.accept(Void, new ConnectionHander());
Where ConnectionHander is an implementation of CompletionHandler that deals with client connections.
The thread that makes the accept call can then continue doing other work and the NIO API will deal with scheduling the callback to the CompletionHandler when a client connection is made (I believe this is an OS level interupt).
The alternative code might look like this:
SocketChannel socketChannel = serverSocketChannel.accept();
Depending on the mode, the calling thread is now blocked until a client connection is made or null is returned leaving you to poll. In both cases, it's you that has to deal with the threads, which generally means more work.
At the end of the day, you take your pick based on your particular use-case, though I've generally the former produces clearer more reliable code.
I am developing a peer to peer application.
in that each peer has one server socket channel and a socket channel,..
Now i need two selectors to handle the connection for server socket channel and socket channel,...
SelectorProvider seems to be a singleton class and it fices only a single instance of Selector,.. which i cant able to use for both the socket channel,..
is there a way to use two selectors in a single instance of a program,..
private ServerSocketChannel svrScktChnl;
private SocketChannel socketChannel;
two selector
public Selector selector=null;
public Selector playerSelector=null;
i am try to intialize these selector separately one for server socket channel and another for socket channel,..
But i cant initialize once again because it throws an error,,..
Now i need two selectors to handle the connection for server socket channel and socket channel,...
No you don't. You can use the same Selector for both, unless for some reason not stated here you want to handle them in separate threads, which is really a violation of everything that NIO stands for.
SelectorProvider seems to be a singleton class
False. SelectorProvider.provider() returns a singleton, but you don't need to use it: there are APIs everywhere that let you specify your own provider. Not that it's relevant, because:
and it fices only a single instance of Selector
False. I don't know what you mean by 'fices', but SelectorProvider.openSelector() returns a new Selector every time you call it, which you could have discovered for yourself without the luxurious technique of posting a question here and waiting possibly forever for a possibly incorrect answer, even if the Provider itself was a singleton, which it isn't.
.. which i cant able to use for both the socket channel,..
No. Clearly you've never actually tried it. You need to understand that this is an empirical science where you are expected to conduct your own experiments. Posting questions on Internet sites and sitting back waiting for the answers is not an efficient use of your time or anybody else's, and it is not calculated to deliver the correct answer as quickly as doing your own work.
it throws an error
You can't seriously expect anyone to help you with as little information as that. Would you accept that as a bug report from a customer?
I am planning to use java NIO for my project, but one of my requirement is to keep the requests configurable, i.e. the client can select the request to be: 1. blocking, 2. non blocking.
So, is it possible to use NIO in a sync. way?
There is an option on the client code when creating the channel:
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(true);
But, I get this error when I make it as true.
This is the client code I am using from this tutorial.
java.nio.channels.IllegalBlockingModeException
at java.nio.channels.spi.AbstractSelectableChannel.register(AbstractSelectableChannel.java:172)
at java.nio.channels.SelectableChannel.register(SelectableChannel.java:254)
at com.dds.client.DDSClient.run(DDSClient.java:77)
at java.lang.Thread.run(Thread.java:680)
The javadocs for register(...) state that if you call the method on a channel that is in blocking mode, that exception will be thrown. A selector can only handle a non-blocking channel.
You need to change your code to use a blocking operations (e.g. read or write) rather than register and select when you want blocking semantics.
You can't use select() on a blocking channel, as the Javadocs say. You more or less have to use the model of a thread per channel.
What is the reason for this strange requirement?
We have a simple client server architecture between our mobile device and our server both written in Java. An extremely simple ServerSocket and Socket implementation. However one problem is that when the client terminates abruptly (without closing the socket properly) the server does not know that it is disconnected. Furthermore, the server can continue to write to this socket without getting any exceptions. Why?
According to documentation Java sockets should throw exceptions if you try to write to a socket that is not reachable on the other end!
The connection will eventually be timed out by Retransmit Timeout (RTO). However, the RTO is calculated using a complicated algorithm based on network latency (RTT), see this RFC,
http://www.ietf.org/rfc/rfc2988.txt
So on a mobile network, this can be minutes. Wait 10 minutes to see if you can get a timeout.
The solution to this kind of problem is to add a heart-beat in your own application protocol and tear down connection when you don't get ACK for the heartbeat.
The key word here (without closing the socket properly).
Sockets should always be acquired and disposed of in this way:
final Socket socket = ...; // connect code
try
{
use( socket ); // use socket
}
finally
{
socket.close( ); // dispose
}
Even with this precautions you should specify application timeouts, specific to your protocol.
My experience had shown, that unfortunately you cannot use any of the Socket timeout functionality reliably ( e.g. there is no timeout for write operations and even read operations may, sometimes, hang forever ).
That's why you need a watchdog thread that enforces your application timeouts and disposes of sockets that have been unresponsive for a while.
One convenient way of doing this is by initializing Socket and ServerSocket through corresponding channels in java.nio. The main advantage of such sockets is that they are Interruptible, that way you can simply interrupt the thread that does socket protocol and be sure that socket is properly disposed off.
Notice that you should enforce application timeouts on both sides, as it is only a matter of time and bad luck when you may experience unresponsive sockets.
TCP/IP communications can be very strange. TCP will retry for quite a while at the bottom layers of the stack without ever letting the upper layers know that anything happened.
I would fully expect that after some time period (30 seconds to a few minutes) you should see an error, but I haven't tested this I'm just going off how TCP apps tend to work.
You might be able to tighten the TCP specs (retry, timeout, etc) but again, haven't messed with it much.
Also, it may be that I'm totally wrong and the implementation of Java you are using is just flaky.
To answer the first part of the question (about not knowing that the client has disconnected abruptly), in TCP, you can't know whether a connection has ended until you try to use it.
The notion of guaranteed delivery in TCP is quite subtle: delivery isn't actually guaranteed to the application at the other end (it depends on what guaranteed means really). Section 2.6 of RFC 793 (TCP) gives more details on this topic. This thread on the Restlet-discuss list and this thread on the Linux kernel list might also be of interest.
For the second part (not detecting when you write to this socket), this is probably a question of buffer and timeout (as others have already suggested).
I am facing the same problem.
I think when you register the socket with a selector it doesn't throw any exception.
Are you using a selector with your socket?