Salut,
CigarMan wrote:
> I have been trying to use Grizzly for the past couple of days to write an
> asynchronous TCP/UDP client. Basically, I want my client to write a bunch of
> bytes (request) to a remote server and eventually receive a response as a
> bunch of bytes.
>
> Looking at the unit tests available with Grizzly framework module, it looks
> like I have to write a callbackhandler to handle the asynchronous response.
> Unfortunately I don't understand the callbackHandler interface.
>
> In TCPAsynchQueueReaderTest.java, the method public void
> onConnect(IOEvent<Context> ioEvent) seems to register a key with the OP_READ
> event.
>
> ioEvent.attachment().getSelectorHandler().register(key,
> SelectionKey.OP_READ);
>
> First of all, I'm kind of lost to what that whole registration means, I have
> very little cue as to what this onConnect method is trying to achieve (I
> would really appreciate if you could post references on your websites so
> that new developpers can get the appropriate background knowledge before
> digging into your framework). I assume this has to do with having the
> selectionKey try to perform a read operation once a connection is
> established with the client.
>
> But yet in the same example, the onRead and onWrite method do nothing!
You should take a look at the TCPConnectorHandler/UDPConnectorHandler as
a starter. They allow you to read/write bytes easily.
>
> Basically, as a user, I need to know where can I put my application code
> that will get the bytes received and perform my business logic (I would
> really like to understand how to write a callbackhandler! :.).
Right. The CallBackHandler is exactly what you need to customize and set
on the ConnectorHandler. As a very simple example:
> private final CallbackHandler createTCPCallbackHandler
> (final ConnectorHandler connectorHandler, final TargetTuple tt){
> CallbackHandler<Context> callbackHandler = new CallbackHandler<Context>() {
>
Below is the onConnect implementation that you can use as it is.
> public void onConnect(IOEvent<Context> ioEvent) {
> SelectionKey key = ioEvent.attachment().getSelectionKey();
> connectorHandler.finishConnect(key);
> controller.registerKey(key, SelectionKey.OP_READ,
> Controller.Protocol.TCP);
> }
>
The onRead will be called when bytes are available.
> public void onRead(IOEvent<Context> ioEvent) {
> try {
> Context ctx = ioEvent.attachment();
> SelectionKey key = ctx.getSelectionKey();
> if (!key.isValid()) {
> return;
> }
>
> // disable OP_READ on key before doing anything else
> key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));
// READ bytes
((SocketChannel)key.channel()).read(ByteBuffer)
// Do something with the bytes
> }
> }
>
the onWrite will be invoked when bytes are available.
> public void onWrite(IOEvent<Context> ioEvent) {
// Write your bytes
((SocketChannel)key.channel()).write(ByteBuffer)
> }
> };
> return callbackHandler;
> }
So a simple snipet would consist of:
TCPConnectorHandler mtCh = new TCPConnectorHandler();
mtCh.setCallbackHandler(new MyCallBackHandler());
mtCh.connect(...);
...
mtCh.read(ByteBuffer, true);
...
mtCh.write(ByteBuffer, true);
Here you will use a special read/write functionality Grizzly is
offering, which is to read/write bytes using a temporary Selector pool.
It behave the same way as blocking IO, but using non-blocking IO under
the hood, giving great performance.
>
> Is there a higher level API provided with the Grizzly framework for writing
> basic clients and servers that send bytes over TCP/UDP (not HTTP)?
The TCPConnectorHandler/UDPConnectorHandler is the place to start. Have
you see this blog:
Yes our documentation is really bad...we are working to fix the problem.
>
> Also, one last question (for now :.), do I need a protocol filter on the
> server side if every write operation write operation from the client writes
> a full request to the channel? (Sorry, I don't really understand behind the
> rationale of the protocolfilter, I don't really understand what kind of
> issue it addresses.
Since you only need client side component, you don't need to use
ProtocolFilter/ProtocolChain. You usually use them when you write a
server side component, or you use a protocol (like SIP) where a client
can becomes a server, and vice versa.
For now, let's work on the TCPConnectorHandler/UDPConnectorHandler.
>
>
> Thanks for your help,
>
>
> Simon
>
>
> P.S.: Don't hesitate to write back in french if you feel like it, I'm from
> Montreal.
Hey hey :-)
>
> Once I get a better understanding of how to write a basic Grizzly asynch
> client and server, I will try to write a tutorial for newbies (like myself)
> about it. I'll let you know.
That would be great!!!
Thanks
-- Jeanfrancois