How to handle 2 byte message length + message for a TCP Server ?

363 views
Skip to first unread message

murtuza chhil

unread,
Sep 25, 2017, 2:03:47 AM9/25/17
to vert.x

I have the following piece of code , mimicked from https://groups.google.com/d/msg/vertx/LA8tk0RbjKU/zH7URQ2J0NQJ

I injected the following through a vertx netclient.
byte[] b = { 0, 4, 0x31, 0x32, 0x33, 0x34 }; // length 4, message 1234
The record size size of the parser is not changing, it always seems to parse 2 bytes at a time. Its alternating correctly between size and payload, but payload is always 2 bytes wide.

How do I get around to changing the fixed size of the record parser?

Using vertx.version 3.5.0.Beta1.

Any help is appreciated.

-chhil

import io.vertx.core.AbstractVerticle;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.NetServerOptions;
import io.vertx.core.parsetools.RecordParser;
import io.vertx.example.util.Runner;

public class TCPServer2 extends AbstractVerticle {

    private FrameToken expectedToken = FrameToken.SIZE;
    RecordParser       frameParser   = null;
    @Override
    public void start() throws Exception {

        NetServerOptions opt = new NetServerOptions();
        opt.setIdleTimeout(500); // large to assist in debugging for now
        NetServer server = vertx.createNetServer(opt);

        server.connectHandler(socket -> {
            frameParser = RecordParser.newFixed(2, buffer -> {

                switch (expectedToken) {

                    case SIZE:

                        byte[] b = buffer.getBytes(0, 2);
                        int frameSize = (((b[0]) & 0xFF) << 8) | ((b[1]) & 0xFF);
                        System.out.println("size: " + frameSize);
                        frameParser.fixedSizeMode(frameSize);
                        expectedToken = FrameToken.PAYLOAD;
                        break;

                    case PAYLOAD:
                        System.out.println("Payload: |" + buffer + "|");
                        frameParser.fixedSizeMode(2);
                        expectedToken = FrameToken.SIZE;
                        break;
                }

            });

            socket.handler(frameParser);
        });

        server.listen(44444, "localhost", new Handler<AsyncResult<NetServer>>() {

            @Override
            public void handle(AsyncResult<NetServer> res) {

                if (res.succeeded()) {
                    System.out.println("Server is now listening!");
                }
                else {
                    System.out.println("Failed to bind!");
                }

            }
        });

    }

    public static void main(String[] args) {

        Runner.runExample(TCPServer2.class);

    }

}

Julien Viet

unread,
Sep 25, 2017, 2:35:34 AM9/25/17
to ve...@googlegroups.com
can you tell us what you are trying to achieve ?

the code you are exhibiting uses a FrameToken class that do not exist anymore in Vert.x 3 record parser.

the doc for the record parser can be found here:


Julien

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
Visit this group at https://groups.google.com/group/vertx.
To view this discussion on the web, visit https://groups.google.com/d/msgid/vertx/1d5b8b71-c54e-4753-8eda-ad761036eaf3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

murtuza chhil

unread,
Sep 25, 2017, 2:44:13 AM9/25/17
to vert.x

Hi ,

I am trying to parse a message that has a 2 byte length header prefixed to it.
so if the message is byte[] b = { 0, 4, 0x31, 0x32, 0x33, 0x34 }; // length 4, message 1234
The first 2 bytes will give the length , its 4 in this case, next I want to parse 4 bytes of data, so I set the recordparser size to 4.
Not aware of frame token , but I am surely using the RecordParser class.


I am using Using vertx.version 3.5.0.Beta1 and I tried it with 3.4.2 too.

-chhil

Julien Viet

unread,
Sep 25, 2017, 3:08:07 AM9/25/17
to ve...@googlegroups.com
Hi,

that makes sense now :-)

you can look at how the clustered EventBus uses the record parser to parse its protocol:


basically it uses fixed size mode and update the size according to wether it’s parsing the len prefix or the actual body.

Julien

chhil

unread,
Sep 25, 2017, 3:23:55 AM9/25/17
to ve...@googlegroups.com
Hi,
Will try to go though the link and see if it helps me and get back.

Thanks
-chhil

To unsubscribe from this group and stop receiving emails from it, send an email to vertx+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to a topic in the Google Groups "vert.x" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/vertx/_8FBnsVqY_4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to vertx+unsubscribe@googlegroups.com.

murtuza chhil

unread,
Sep 25, 2017, 4:47:58 AM9/25/17
to vert.x

https://github.com/eclipse/vert.x/blob/master/src/main/java/io/vertx/core/eventbus/impl/clustered/ClusteredEventBus.java#L317

RecordParser parser = RecordParser.newFixed(4);

There is no signature for mewFixed that takes one param. I am at a loss now.


-chhil

chhil

unread,
Sep 25, 2017, 5:59:10 AM9/25/17
to ve...@googlegroups.com
Hi,

Did have to change it a bit as newFixed takes 2 params and because of that I did not know what to do with setOutput from the github code.

Basically did not make any progress, stuck at the code reading 2 bytes at a time.

Would really appreciate it if some assist me fixing this. 


package io.vertx.book.http;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.NetServerOptions;
import io.vertx.core.net.NetSocket;
import io.vertx.core.parsetools.RecordParser;
import io.vertx.example.util.Runner;

public class TCPServer2 extends AbstractVerticle {

    private
 FrameToken expectedToken = FrameToken.SIZE;
    RecordParser       parser, frameParser = null;

    private Handler<NetSocket> getServerHandler() {
        return socket -> {
            parser = RecordParser.newFixed(2, new Handler<Buffer>() {// this line varies from the original
                int size = -1;

                public void handle(Buffer buff) {
                    if (size == -1) { // this is no different than the earlier codes switch statement 
                        byte[] b = buff.getBytes(0, 2);
                        size = (((b[0]) & 0xFF) << 8) | ((b[1]) & 0xFF);
                        System.out.println("size: " + size);

                        parser.fixedSizeMode(size);
                    }
                    else {

                        parser.fixedSizeMode(2);
                        size = -1;

                    }
                }
            });
            // parser.setOutput(handler); // not sure what do I need to do here.
            socket.handler(parser);
        };
    }

    
@Override
    public void start() throws Exception {

        NetServerOptions opt = new NetServerOptions();
        opt.setIdleTimeout(500); // large to assist in debugging for now

        NetServer server = vertx.createNetServer(opt);

        server.connectHandler(getServerHandler());
        // server.connectHandler(socket -> {
        // frameParser = RecordParser.newFixed(2, buffer -> {
        //
        // switch (expectedToken) {
        //
        // case SIZE:
        //
        // byte[] b = buffer.getBytes(0, 2);
        // int frameSize = (((b[0]) & 0xFF) << 8) | ((b[1]) & 0xFF);
        // System.out.println("size: " + frameSize);
        // frameParser.fixedSizeMode(frameSize);
        // expectedToken = FrameToken.PAYLOAD;
        // break;
        //
        // case PAYLOAD:
        // System.out.println("Payload: |" + buffer + "|");
        // frameParser.fixedSizeMode(2);
        // expectedToken = FrameToken.SIZE;
        // break;
        // }
        //
        // });
        //
        // socket.handler(frameParser);
        // });


        server.listen(44444, "localhost", new Handler<AsyncResult<NetServer>>() {

            @Override
            public void handle(AsyncResult<NetServer> res) {

                if (res.succeeded()) {
                    System.out.println("Server is now listening!");
                }
                else {
                    System.out.println("Failed to bind!");
                }

            }
        });

    }

    public static void main(String[] args) {

        Runner.runExample(TCPServer2.class);

    }

}

-chhil


Alexander Lehmann

unread,
Sep 25, 2017, 7:10:47 AM9/25/17
to vert.x
The different signatures of the newFixed method were apparently introduced in the current master, this was not available in 3.5.0 beta1, the corresponding example for 3.5.0 is this https://github.com/eclipse/vert.x/blob/3.5.0.Beta1/src/main/java/io/vertx/core/eventbus/impl/clustered/ClusteredEventBus.java#L315

When setting the output handler, you have to set it only once, either in the newFixed method or you can pass null as handler and set it with .setOutput() after the Parser was created. For the example, it should be sufficient to set the handler in the creating method and use the inline subclass for your code (the behaviour will not change either way I assume though).

The code looks ok, I will give it a try this evening when i have time.
-chhil

--
You received this message because you are subscribed to a topic in the Google Groups "vert.x" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/vertx/_8FBnsVqY_4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to vertx+un...@googlegroups.com.

--
You received this message because you are subscribed to a topic in the Google Groups "vert.x" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/vertx/_8FBnsVqY_4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to vertx+un...@googlegroups.com.

murtuza chhil

unread,
Sep 25, 2017, 7:26:02 AM9/25/17
to vert.x
Thanks Alexander.
Appreciate you looking into the code.
I still cant get past the buffer being read 2 bytes at a time.
Now I set null as the output handler and set it once later on.
    private Handler<NetSocket> getServerHandler() {
        return
 socket -> {
            parser = RecordParser.newFixed(2, null);

            Handler<Buffer> handler = new Handler<Buffer>() {

                
int size = -1;

                public void handle(Buffer buff) {
                    if (size == -1
) {
                        
byte[] b = buff.getBytes(0, 2);
                        size = (((b[0]) & 0xFF) << 8) | ((b[1]) & 0xFF);
                        System.out.println("size: " + size);

                        parser.fixedSizeMode(size);
                    }
                    else {

                        parser.fixedSizeMode(2);
                        size = -1
;

                    }
                }
            };
            parser.setOutput(handler);
            socket.handler(parser);
        };
    }

-chhil

Alexander Lehmann

unread,
Sep 25, 2017, 7:38:10 AM9/25/17
to vert.x
I was wondering, what does the program currently print?

Assuming that the fixed size does not change, it should receive two packets, the first one with size 4, but then only 2 bytes payload, the second with size 13108 (0x3334)

murtuza chhil

unread,
Sep 25, 2017, 7:43:57 AM9/25/17
to vert.x


First time around it prints size: 4 and second time around it goes into the else part, that time the buffer has 12. Third time around it prints size: 13108.

-chhil

murtuza chhil

unread,
Sep 25, 2017, 10:32:30 PM9/25/17
to vert.x

Hi,

This morning after a reboot, for whatever reason, I am getting the 2 bytes in the first iteration and 4 bytes as expected in the second iteration.
I apologize for wasting your time.

-chhil

Mumuney Abdlquadri

unread,
Sep 26, 2017, 4:17:16 AM9/26/17
to ve...@googlegroups.com
Hi Chhil,

Are we trying to use Vert.x inside JPOS :)



To unsubscribe from this group and stop receiving emails from it, send an email to vertx+unsubscribe@googlegroups.com.

chhil

unread,
Sep 26, 2017, 4:39:22 AM9/26/17
to ve...@googlegroups.com
Hi Mumuney, 

I am just experimenting, and haven't decided on using it inside JPOS or standalone.  
What gave it away the,  the 2byte length header or the code that calculates the length ;-)  

-chhil

To unsubscribe from this group and all its topics, send an email to vertx+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages