Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Java NIO channel never becomes readable

Reply
Thread Tools

Java NIO channel never becomes readable

 
 
nooneinparticular314159@yahoo.com
Guest
Posts: n/a
 
      03-18-2008
> All that indicates that there is nothing to write, i.e. position = limit.
>
> NB I think the result of a ByteBuffer.wrap() is already flipped for some
> reason.
>
> Re OP_READ, are you registering the channel for OP_READ?


I'm initially registering the channel as:
AcceptedChannel.register(ChannelSelector, SelectionKey.OP_READ |
SelectionKey.OP_WRITE);
(I've also tried setting it up intially as:
AcceptedChannel.register(ChannelSelector, SelectionKey.OP_READ);
but that doesn't seem to work (as it shouldn't, since I need to be
able to both read and write.)

The next thing it hits (assuming that there is a key) is usually if
(NextKey.isWritable())
(It hits the test for readability first, but I never get a readable
channel)

It gets the appropriate channel based on that key:
NetworkDataHandler Handler = DataHandlerContainer.Get((SocketChannel)
NextKey.channel());

and then the object associated with that specific channel tries to set
up a message and write to it:
MessageHandlerForThisChannel.SendTestMessage();

That creates a test message (currently a string about wishing that my
program would work!), encodes it in a byte array, and adds it to my
outgoing message queue.

A message sending method is then called, which checks for messages on
the queue. If any exist, it gets the next one and places it in the
SendBuffer. It then does a

Channel.write(SendBuffer);

to write out the data. I've tried various combinations of registering
teh channel for OP_READ, OP_READ | OP_WRITE, or OP_WRITE after this,
and none of them worked (although registering for read only certainly
prevented more data from being written. )

After the data is written out to the channel, it definitely appears on
the remote host. Using Ethereal, I've been able to confirm that both
clients send the test message to each other. Using Telnet, I've also
been able to confirm that the message is sent to remote clients.
Ethereal also confirmed that both clients are writing to and from the
same ports on each machine, so they are clearly using the same channel
in each direction. However, despite the data making it at least as
far as the remote host, the OP_READ is never triggered, and therefore
the data is never read. Unless, of course, I send the data through
telnet, in which case it is. Actually, I also tried writing a non-
blocking client that does an OP_CONNECT instead of a read or write,
that one seems to be able to get data through to the client (although
it doesn't try to read any.) That client uses the same reading and
writing methods as my regular client. Only the setup is different.

Any ideas? What else can I try?

Thanks!
 
Reply With Quote
 
 
 
 
EJP
Guest
Posts: n/a
 
      03-18-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> (I've also tried setting it up intially as:
> AcceptedChannel.register(ChannelSelector, SelectionKey.OP_READ);
> but that doesn't seem to work (as it shouldn't, since I need to be
> able to both read and write.)


Nothing to do with it. You can write any time. You should only register
OP_WRITE when you got a zero return from channel.write(); then when
OP_WRITE fires, repeat the write, and if it succeeded completely (i.e.
!buffer.hasRemaining()), deregister OP_WRITE.

> The next thing it hits (assuming that there is a key) is usually if
> (NextKey.isWritable())


Of course. The channel is almost always writable, unless you've filled
the send buffer. That's why you should only register OP_WRITE when you
know that has occurred.

> (It hits the test for readability first, but I never get a readable
> channel)


So there is nothing to read.

> However, despite the data making it at least as
> far as the remote host, the OP_READ is never triggered, and therefore
> the data is never read.


If the remote host is written the same way as this, it is probably too
busy spinning on OP_WRITE. In any case until the remote host has read
the request it won't write a response, will it? which would explain why
you never get a readable channel in the client.

> Unless, of course, I send the data through telnet,


Can't account for that, but there are enough mistakes already that you
need to fix and re-test.

in which case it is. Actually, I also tried writing a non-
> blocking client that does an OP_CONNECT instead of a read or write,
> that one seems to be able to get data through to the client (although
> it doesn't try to read any.) That client uses the same reading and
> writing methods as my regular client. Only the setup is different.


If you use OP_CONNECT you must deregister it when it fires, as under the
hood it's the same as OP_WRITE.
 
Reply With Quote
 
 
 
 
nooneinparticular314159@yahoo.com
Guest
Posts: n/a
 
      03-19-2008
On Mar 18, 4:26*pm, EJP <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > (I've also tried setting it up intially as:
> > AcceptedChannel.register(ChannelSelector, SelectionKey.OP_READ);
> > but that doesn't seem to work (as it shouldn't, since I need to be
> > able to both read and write.)

>
> Nothing to do with it. You can write any time. You should only register
> OP_WRITE when you got a zero return from channel.write(); then when
> OP_WRITE fires, repeat the write, and if it succeeded completely (i.e.
> !buffer.hasRemaining()), deregister OP_WRITE.
>
> > The next thing it hits (assuming that there is a key) is usually if
> > (NextKey.isWritable())

>
> Of course. The channel is almost always writable, unless you've filled
> the send buffer. That's why you should only register OP_WRITE when you
> know that has occurred.
>
> > (It hits the test for readability first, but I never get a readable
> > channel)

>
> So there is nothing to read.
>
> > However, despite the data making it at least as
> > far as the remote host, the OP_READ is never triggered, and therefore
> > the data is never read.

>
> If the remote host is written the same way as this, it is probably too
> busy spinning on OP_WRITE. In any case until the remote host has read
> the request it won't write a response, will it? which would explain why
> you never get a readable channel in the client.
>
> > Unless, of course, I send the data through telnet,

>
> Can't account for that, but there are enough mistakes already that you
> need to fix and re-test.
>
> * in which case it is. *Actually, I also tried writing a non-
>
> > blocking client that does an OP_CONNECT instead of a read or write,
> > that one seems to be able to get data through to the client (although
> > it doesn't try to read any.) *That client uses the same reading and
> > writing methods as my regular client. *Only the setup is different.

>
> If you use OP_CONNECT you must deregister it when it fires, as under the
> hood it's the same as OP_WRITE.


I'm confused. If you never register OP_WRITE unless the client can't
write to the channel, then how does the code to write in the first
place ever get called? ie. You test to see if the channel is
writable. If it is, you write something. If it isn't, that section
of code will never get called, and you will never get the chance to
write.

>> (It hits the test for readability first, but I never get a readable
>> channel)


>So there is nothing to read.


But I'm sure that there is something to read. In fact, I can have one
client write repeatedly until the receive buffer gets filled. Then it
stops writing because it can no longer do so. But even when this
happens, OP_READ is never triggered. Huh?

>If the remote host is written the same way as this, it is probably too
>busy spinning on OP_WRITE. In any case until the remote host has read
>the request it won't write a response, will it? which would explain why
>you never get a readable channel in the client.


In this case, both clients are identical. The way it works is one
client connects to the other. when it does so, it sends some initial
data. Both clients send this data first thing, before anything else
happens. So they should both have data to read. But somehow, they
don't.

The OP_CONNECT isn't actually part of my client code - it was just
there from a testing program. But it does trigger a read on the
client...

I'll try setting everything to OP_READ except in the situation you
mentioned and report back what happens. I'm pretty sure that I've
tried this before though, and when I do, the clients just sit there
and don't write (and therefore have nothing to read). I'll also try
removing the test for writing, as I think you've suggested, and maybe
that will help. More shortly...

Thanks!
 
Reply With Quote
 
Mark Space
Guest
Posts: n/a
 
      03-19-2008
(E-Mail Removed) wrote:

> I'm confused. If you never register OP_WRITE unless the client can't
> write to the channel, then how does the code to write in the first


I'm guessing here, but EJP did say to try to write first. Then, if the
bytes written was 0, only then register OP_WRITE.

It makes sense to me. Only register OP_WRITE if the out-bound channel
is stuffed full and won't take any more, that's when you need to be
notified when it's ready again. Otherwise, just stuff more in there.
 
Reply With Quote
 
nooneinparticular314159@yahoo.com
Guest
Posts: n/a
 
      03-19-2008
Results:
Always setting to OP_READ: one client manages to write something to
the channel, but the other never gets a readable key, and therefore
never looks in the buffer.

Always setting to OP_READ + removing the test for NextKey.isWritable:
I get a class casting exception when I try to do:

DataHandlerContainer.Get((SocketChannel) NextKey.channel());

(This has never happened before. The DataHandlerContainer contains
the objects that I use to write to channels. I have one such object
per channel. I have many clients that I might need to communicate
with, which is why I am dependent on the key to tell me which channel
to write to, and therefore which object to have writing to that
channel.)

Always setting to OP_READ, but setting the channel to OP_READ |
OP_WRITE just before I write has no effect. One client still writes.
The other never does. Neither reads. However, occasionally a crash
occurs, and the buffer on the other client suddenly becomes readable
(once with actual data in the buffer!)
 
Reply With Quote
 
EJP
Guest
Posts: n/a
 
      03-19-2008
(E-Mail Removed) wrote:
> Always setting to OP_READ: one client manages to write something to
> the channel, but the other never gets a readable key, and therefore
> never looks in the buffer.


Did the write return a non-zero result? If not, you haven't written
anything yet.

> Always setting to OP_READ + removing the test for NextKey.isWritable:
> I get a class casting exception when I try to do:
>
> DataHandlerContainer.Get((SocketChannel) NextKey.channel());


That's a bug in your code.

> Always setting to OP_READ, but setting the channel to OP_READ |
> OP_WRITE just before I write has no effect.


It's not *supposed* to have any effect. These OP_* things just tell the
selector what you want it to wake up on. They're not there to determine
what I/O APIs you're allowed to call.

You'll have to show us some code for this to get any further. You seem
to have a lot of misconceptions about how all this is supposed to work.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Channel Switch in GO, can I do this with java.nio Jan Burse Java 10 11-06-2011 09:32 PM
and becomes or and or becomes and Stef Mientki Python 9 05-28-2011 02:04 PM
Java.NIO channel never becomes writable nooneinparticular314159@yahoo.com Java 6 03-17-2008 06:52 AM
Reversing Bit Order.. i.e. MSB becomes bit 0, LSB becomes bit 15 benn686@hotmail.com C++ 9 08-22-2007 12:13 AM
RAM - 2gb becomes 4gb becomes 2gb b Computer Support 10 04-27-2006 11:58 PM



Advertisments