Problems with sending and receiving binary data

Issue #49 closed
Martin Kovacs created an issue

Hey,

I want to send and receive binary data in jmeter.

For that I created a testplan.testplan.PNG

In the WebSocket Single Write Sampler I send a number in binary format. send.PNG

On the serverside I have a OnMessage method:

 @OnMessage
    public void onMessageBinary(byte[] message, Session session) throws IOException{



        System.out.println("Client message: " + message);

        limit = Integer.parseInt(new String(message, StandardCharsets.UTF_8));

The print method show me this: Client message: [B@25ac82ec

After that I want to convert this back to a Integer (limit). With this Integer I read a number of datasets from my db and send it back to jmeter.

//read data from mongoDB
        String data= mongo.readNumberOfDocuments(limit).toString();
        session.getBasicRemote().sendBinary(ByteBuffer.wrap(data.getBytes("UTF-8")));

Now there are some problems. The serverside throws this exception:

java.lang.NumberFormatException: For input string: " "
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:569)
    at java.lang.Integer.parseInt(Integer.java:615)
    at websocket.EchoEndpoint.onMessageBinary(EchoEndpoint.java:116)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)

So I'm not sure what kind of data format the message from jmeter is?

Additionally if I send the data binary to jmeter I can't see the response data in the Results Tree. The Response data field is empty.

I think the problme is on the serverside because receive and send the binary messages wrong to jmeter? But I'm not sure.

Hope you can help me with this problem!

Comments (8)

  1. Peter Doornbosch repo owner

    Hi,

    The data you enter in the sampler (data field) is interpreted as hexadecimal. So if you type 100, this is interpreted as two bytes: 0x10 0x00.

    You seem to think the data is send as UTF-8 characters, but that is not the case when sending binary data (it is when sending text data). If you want to send the number 100 as a string in a binary websocket message, you should encode it as ascii characters, so that would be 0x31 0x30 0x30.

    As explain both in the readme file and in issue 20 (that you commented on), binary data can be viewed in the Results Tree in the Response data tab, when you select "Binary" in the type field.

    Hth Peter

  2. Martin Kovacs reporter

    Hi,

    thank you very much for you answer.

    Yes you are right. I tried to enter 100 and thought that the plugin converts this in binary with UTF-8 with a function like:

    data.getBytes("UTF-8") 
    

    and send this with the send method to the server.

    So if I want to send different numbers to the server in binary I have to encode the numbers in ascii before sending them, right?

    Oh no, I forgot to change the tab to binary... I'm sorry for wasting your time.

    Thanks a lot for your help!!! Your plugin is really great work!

  3. Peter Doornbosch repo owner

    "So if I want to send different numbers to the server in binary I have to encode the numbers in ascii before sending them, right?"

    That is a possibility. It all depends an what you want. I'd say that if you want to send over text, using a text-frame would be much easier. The binary frame is really just that: binary data. You can put in whatever you want and using the encoding that you want. Of course, encoding as (ascii) text is possible, but you could also send real binary data, so 100 (decimal) is 0x64 hex, so the payload would only be one byte.... ;-). It all depends on your use case.

    Cheers, Peter

  4. Martin Kovacs reporter

    Okay I realize I'm not really deep involved in working with binary data and sending binary data.

    I'm student and actually I'm working at my bachelor thesis. Thats why I don't have really much experience in this area.

    The task in my thesis is to make different tests with websockets and mqtt. So my goal is to do different latency tests over different network standards like WLAN, Ethernet... . In this tests I send different numbers of datasets from the server/broker to jmeter and measure the latency over the network. In my tests I'am working with websockets AND mqtt as application layer protocol.

    For mqtt I use the plugin https://github.com/hemikak/mqtt-jmeter for the latency tests over mqtt. And for websockets I use your plugin.

    Because mqtt only support sending data binary I wanted to do the same over websockets to make a better conclusion between the latencies.

    So thats why I want to send these numbers...

    Do you have a better idea for testing that?

    Martin

  5. Peter Doornbosch repo owner

    Hi Martin,

    For that purpose, i think it doesn't really matter what content you are sending over the line, does it? So your current approach seems fine to me. I guess the only thing that matters for your research is the length of the payload, so you can have comparable tests for mqtt and ws.

    Cheers, Peter

  6. Martin Kovacs reporter

    Hi Peter,

    In my case I have small data sets with random values. I wrote one million datasets in my db. The datasets in the db are in json format. For my tests I use every time the same data but I vary the number of datasets that I send. Here can you see the structure of one dataset.

    Frame-Size-OneDataset.PNG

    So if I send one dataset, the lenght is 70 bytes. If I send more datasets for example 10 datasets I have not exactly about ten times more bytes. But the size of receiving bytes I can check and see in jmeter. With this and the read time I can calculate the throughput of the payload in Mb/s.

    Before I asked my question to you, I thought that if I send the datasets as binary and not as text, the payload size will be smaller. And that sending the data as binary could reduce more the bandwidth and with this I can reduce the latency of sending data over the network... But I think I am on a wrong way because whether I send the data as binary or I send the data as text and watching it in chrome dev tools the size of the server response is every time exactly 70 bytes (if I send one dataset). So I think it doesn't matter whether I send the data as text or binary.

    So if I want to reduce bandwidth and latency I have to convert the data in binary to make the payload smaller on serverside and send them to jmeter. But if I want to use the data later in javascript to render a line graph I have to convert it back to text or json?

    How can I convert the data from string to raw binary to reduce payload size and sending it over websockets? How can I convert the raw binary back in json to use the data values? How I have to send integer values (numbers) in binary from jmeter meter to the server and how can I convert the binary to a integer on serverside?

    I'm not sure how I can do this, or whats the best way to do something like that.... And I'm not sure if I am on the right side with this idea.

    Do you have a idea?

    Martin

  7. Peter Doornbosch repo owner

    Hi,

    "So I think it doesn't matter whether I send the data as text or binary." => Correct. When sending text (as you do, json is text) sending it as text or binary doesn't make any difference, the payload will exactly be the same.

    To reduce data size: - for text data you could consider compressing it (zip, gzip, ...) - for numeric data you could encode the numbers as integers instead off sending the string representation.

  8. Log in to comment