Link to home
Start Free TrialLog in
Avatar of matthew016
matthew016Flag for Belgium

asked on

question on a nio example (1)


This is the tutorial I try to fully understand:
(I may ask several questions about this tutorial)

I understand the whole sever-side code, but I don't understand the logic client-side.
Firstly, this part :

private SocketChannel initiateConnection() throws IOException {
      // Create a non-blocking socket channel
      SocketChannel socketChannel =;

      // Kick off connection establishment
                  .connect(new InetSocketAddress(this.hostAddress, this.port));

      // Queue a channel registration since the caller is not the
      // selecting thread. As part of the registration we'll register
      // an interest in connection events. These are raised when a channel
      // is ready to complete connection establishment.
      synchronized (this.pendingChanges) {
            this.pendingChanges.add(new ChangeRequest(socketChannel,
                        ChangeRequest.REGISTER, SelectionKey.OP_CONNECT));

      return socketChannel;

and the paragraph below (not any of these sentences, explain all of them please in a more simple way).

Thanks for the help!
Avatar of Kevin Cross
Kevin Cross
Flag of United States of America image

The code seems pretty well commented.  What exactly in the above don't you understand?
It is establishing a connection to the server.
If we know what specifically doesn't make sense, can try to explain further.
Avatar of matthew016


As I said, any sentence in the paragraph:

In a nutshell, initiating a connection means creating a new non-blocking socket channel, initiating a (non-blocking) connection and registering an interest in finishing the connection. The only wrinkle is that, since the calling thread is not the selecting thread, the last step must be deferred.

> Who is the calling thread ? What must be deferred ?

We don't wake the selecting thread up because the method that calls this will want to queue some data to be written when the connection is completed.

> Why would we want to wake up the selecting thread anyway, and why don't we do it if we need to ? Didn't get the explanation.

Waking the selecting thread up here opens us up to a race condition where the connection is completed by the selecting thread before the calling thread queues the data and OP_WRITE is never set on the channel's selection key.

> Didn't get it
Typically with this kind of application, you will have a client (selecting) process/thread that uses other worker (calling) threads to do certain tasks.  Hopefully, I didn't swap the two, but point remains the same that it is typical for the client thread to utilize additional threads for tasks that have potential of locking or not returning to give you ability to cancel / exit from client if process goes a stray to connect to the server for example.

The registration of "connection complete" has to be deferred.

Per above, since the client thread needs to be told that the worker thread is done connecting, it must be "woken up" at some point; however, we don't want to do this too soon per the next paragraph which explains that this could result in a "race condition" (  

Hopefully that helps.
Hello, I know what threads are for and I understand what a race condition is.
However, I dont understand *in this specific tutorial* who is the calling thread and who is the selecting thread at the time he's calling "initiateConnection". At that time, it seems to me there is only one thread.

To register the accept event server-side, he didn't use a pending queue. Why client-side is he using one to register the connect event ? (that's what he's trying to explain I guess with the race condition and the selecter/calling thread, but I don't understand the code)
Did you read the first part of my post regarding client applications.  The worker thread that is calling Initiateconnection (hence the calling thread) would be different than the main thread of execution for the client (selecting thread).
And also (sorry), remember that there is a socket selector thread that is used to find the open channel on which new connection requests will be accepted.  Therefore, even if you use on thread on the client side, there is still a second thread involved here aside from the server thread.  
I can't see not more than one thread in the code client-side, that's the first problem...

This is the main function:

NioClient client = new NioClient(InetAddress.getByName("localhost"), 9090);
Thread t = new Thread(client);
RspHandler handler = new RspHandler();
client.send("GET / HTTP/1.0\r\n\r\n".getBytes(), handler);
Thread t = new Thread(client);

That is starting a new thread which I believe you are counting as the one.  Consider though, you are already in a thread of execution which is running that code.  :) So you are spawning a new thread from one you are already in.  So this was my original discussion on most times you have two threads on the client side.

However, per my last post, when I went through the tutorial specifically, I saw that there was a selector thread whose job was to find open socket and return it, so there is another thread/process involved as it appeared separate from the client and server threads.
ok, there is thread t and there is the main thread.
However, I still don't know who is the calling thread and selecting thread and how a race condition may occur.

Thread t is the selecting thread.
DO you know why he does :


For the client selecting thread ?

For the server selecting thread he didn't do so.
(forget about the calling and selecting threads, I'll close this question as soon as you answer the last note about setDaemon)
Avatar of Kevin Cross
Kevin Cross
Flag of United States of America image

Link to home
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial

By the way, I found out which was the calling and select thread he was talking about :

NioClient client = new NioClient(InetAddress.getByName("localhost"), 9090);
Thread t = new Thread(client);
t.start(); <---- selecting thread (will listen for events)
RspHandler handler = new RspHandler();
client.send("GET / HTTP/1.0\r\n\r\n".getBytes(), handler);   <---- the calling thread