Avatar of matthew016
matthew016
Flag for Belgium asked on

question on a nio example (1)

Hi,

This is the tutorial I try to fully understand:
http://rox-xmlrpc.sourceforge.net/niotut/index.html
(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 = SocketChannel.open();
      socketChannel.configureBlocking(false);

      // Kick off connection establishment
      socketChannel
                  .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!
Java

Avatar of undefined
Last Comment
matthew016

8/22/2022 - Mon
Kevin Cross

The code seems pretty well commented.  What exactly in the above don't you understand?
It is establishing a connection to the server.
Kevin Cross

If we know what specifically doesn't make sense, can try to explain further.
matthew016

ASKER
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
Your help has saved me hundreds of hours of internet surfing.
fblack61
Kevin Cross

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" (http://en.wikipedia.org/wiki/Race_condition).  

Hopefully that helps.
matthew016

ASKER
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)
Kevin Cross

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).
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Kevin Cross

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.  
matthew016

ASKER
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);
t.setDaemon(true);
t.start();
RspHandler handler = new RspHandler();
client.send("GET / HTTP/1.0\r\n\r\n".getBytes(), handler);
handler.waitForResponse();
Kevin Cross

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.
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
matthew016

ASKER
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.
matthew016

ASKER
DO you know why he does :

t.setDaemon(true);

For the client selecting thread ?

For the server selecting thread he didn't do so.
matthew016

ASKER
(forget about the calling and selecting threads, I'll close this question as soon as you answer the last note about setDaemon)
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER CERTIFIED SOLUTION
Kevin Cross

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
matthew016

ASKER
Thanks!

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.setDaemon(true);
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
handler.waitForResponse();