mal
mal

Reputation: 3204

NIO Selector OP_READ and OP_WRITE, some questions about handling them

I've been following this tutorial, it's quite helpful and most things are making sense.

If you look on page 34 you'll see this snippet of code:

} else if ((key.readyOps() & SelectionKey.OP_READ)
== SelectionKey.OP_READ) {
// Read the data
SocketChannel sc = (SocketChannel)key.channel();
// ...
}

What exactly is going on here, the single ampersand means both conditions are checked, so, in this case key.readyOps() will return a number whose bits represent the operations that are available to work on. SelectionKey.OP_READ is another int. So I understand how these two relate.
So the first test (key.readyOps() & SelectionKey.OP_READ) in my head this will return true or false. true if key.readyOps() == SelectionKey.OP_READ is that correct? or is it if key.readyOps() contains the correct bits set for OP_READ. The start of that particular if statement contains the same test, but with OP_ACCEPT instead of OP_READ. You can see that on page 33.

Then the next test in the sequence == SelectionKey.OP_READ what's happening here?
In my head I see that evaluating like this:

if(true == SelectionKey.OP_READ)

or

if(false == SelectionKey.OP_READ)

But that can't be right can it? since OP_READ is an int? Or will an int be true for anything except 0? I don't think that's right either because the second part is redundant.

The above works fine, I'm just not clear on what's actually going on with the if test.

So next, I'm wondering about handling reading once the above evaluates to true.

First I call SocketChannel sc = (SocketChannel) key.channel(); to get a handle on the channel.

Then I ready my buffer and read from the socket with int bytesRead = sc.read(myBuffer);

Now I need to test what was read, correct? So I do something like this:

if(read == -1){

  // The connection has been terminated, handle that. 

}else if(read == 0){

// Check data is complete, if so switch to OP_WRITE 

}else{

 // Read bytes into the buffer

}

So is the above an acceptable thing to do?

the javadoc says the following about OP_READ:

Operation-set bit for read operations. Suppose that a selection key's interest set contains OP_READ at the start of a selection operation. If the selector detects that the corresponding channel is ready for reading, has reached end-of-stream, has been remotely shut down for further reading, or has an error pending, then it will add OP_READ to the key's ready-operation set and add the key to its selected-key set.

Upvotes: 0

Views: 1121

Answers (1)

user207421
user207421

Reputation: 310884

the single ampersand means both conditions are checked

It means the bitwise AND of the two operands is computed. As one of the operands has only a single bit set, only one condition is being checked: OP_READ.

so, in this case key.readyOps() will return a number whose bits represent the operations that are available to work on.

Of course, but the & modifies that.

SelectionKey.OP_READ is another int. So I understand how these two relate.

What follows doesn't justify your confidence about that.

So the first test (key.readyOps() & SelectionKey.OP_READ) in my head this will return true or false.

Wrong again. It will return zero or SelectionKey.OP_READ. You need to brush up the rules of Java arithmetic.

true if key.readyOps() == SelectionKey.OP_READ is that correct?

No.

or is it if key.readyOps() contains the correct bits set for OP_READ.

See above.

The start of that particular if statement contains the same test, but with OP_ACCEPT instead of OP_READ ... Then the next test in the sequence == SelectionKey.OP_READ what's happening here?

It is testing first for OP_ACCEPT and then for OP_READ.

In my head I see that evaluating like this:

No. See above. You are confused. What you have posted doesn't make sense.

if(true == SelectionKey.OP_READ)

true can't be equal to an integer.

or

if(false == SelectionKey.OP_READ)

Ditto.

But that can't be right can it? since OP_READ is an int?

Correct. So you can't think it.

Or will an int be true for anything except 0?

No. You need to brush up the rules of Java arithmetic.

So next, I'm wondering about handling reading once the above evaluates to true.

First I call SocketChannel sc = (SocketChannel) key.channel(); to get a handle on the channel.

No, to get the SocketChannel from the SelectionKey.

Then I ready my buffer and read from the socket with

    int bytesRead = sc.read(myBuffer);

Now I need to test what was read, correct?

You need to test the result returned by the read() method.

So I do something like this:

    if(read == -1){
        // The connection has been terminated, handle that. 
    }else if(read == 0){

    // Check data is complete

No. If the data was already complete you should already know that, and you wouldn't have called read() again.

// if so switch to OP_WRITE 

No. OP_WRITE is used when a write() has returned zero. No other time.

}else{
    // Read bytes into the buffer

No. The bytes are already in the buffer.

So is the above an acceptable thing to do?

It doesn't begin to make sense. You need to take another good look at the IBM tutorial you cited. The misconceptions you've posted here don't appear there.

Upvotes: 1

Related Questions