1

I have for example here this string

'x���'

Which you may possibly not see depending on the devide you're using. That's the number 2024000250 encoded as a 32 bit signed big endian integer, which I've generated using Node

let buffer = new Buffer(4);
b.writeInt32BE(2024000250).toString();

I'm receiving the 4 bytes in question on the client side but I can't seem to find how to turn them back into an integer...

2 Answers 2

1

I might be dead wrong here. But as far as I remember unicode characters can be between 2-4 bytes. When you transfer your binary data as text to client-side you risk corrupting this information because the client is going to interpret them as unicode.

If I were to convert that text to a blob on client side:

var b = new Blob(['x���'],{type:"application/octet-stream"});
b.size; //10 

As you can see I receive 10 bytes, which is wrong, it should have been 4.

You can transfer the data directly as a binary string, since you are using Node, on the server side:

function createBuffer(v){
    var b = new ArrayBuffer(4),
        vw = new DataView(b);
    vw.setInt32(0,v);
    return b;
}

This will create your buffer, now you cannot just send this as it is to client, either represent it as a json or directly as a binary string. To represent it as binary you don't need the above function, you could have done:

("0".repeat(32) + (2024000250).toString(2)).slice(-32); //"01111000101000111100101011111010"

If you want json, you can do:

function convertBuffToBinaryStr(buff){
    var res = [],
        l = buff.byteLength,
        v = new DataView(buff);
    for (var i = 0; i < l; ++i){
        res.push(v.getUint8(i));
    }
    return JSON.stringify(res);
}

Now try seeing what this outputs:

convertBuffToBinaryStr(createBuffer(2024000250)); //"[120,163,202,250]"

Back on the client-side you have to interpret this:

function interpret(json){
    json = JSON.parse(json);
    return parseInt(json.map((d)=>("0".repeat(8) + d.toString(2)).slice(-8)).join(""),2);
}

Now try:

interpret("[120,163,202,250]"); //2024000250

Note: For your interpret function, you have to use dataView to setUint8 and the use getInt32 at the end, since you are using signed integers, above won't work for all cases.

Sign up to request clarification or add additional context in comments.

7 Comments

Thank you for this thorough answer. The reason why I'm doing this is because I want to only transmit 4 bytes (in this case), JSON or a string of 1s and 0s is definitely not what I'm aiming for. I'm guessing I'll need to look more into transmitting binary data through websockets.
I guess you realized cutting byte-length through text is risky, so you want to make transfer as efficient as possible by eliminating http headers back and forth. Is that correct ?
I might also be dead wrong but I remember I've done this way back in the days using PHP's pack and unpack functions to store some numbers as binary "text" in a file. That didn't end up having any issues and since all the data was just numbers I ended up saving quite some disk space. I'm pretty sure this method can work here again but I'm thinking the interpreter wouldn't be as efficient as I'd like.
Indeed that's what I'm wondering, how can I send just those 4 bytes and have the javascript client decode them just like PHP would.
|
0

Well I finally got around to getting this to work.

It is not quite what I started off with but I'm just gonna post this for some other lost souls.

It is worth mentioning that ibrahim's answer contains most of the necessary information but is trying to satisfy the XY problem which my question ended up being.

I just send my binary data, as binary

let buffer = new Buffer(4);
buffer.writeInt32BE(2024000250);

// websocket connection
connection.send(buffer);

Then in the browser

// message listener
let reader = new FileReader();
reader.addEventListener('loadend', () => {
  let view = new DataView(reader.result);

  // there goes the precious data
  console.log(view.getInt32());
});
reader.readAsArrayBuffer(message.data);

In all honesty this tickles my gag reflex. Why am I using a file reader to get some data out of a binary message? There is a good chance a better way of doing this exists, if so please add to this answer.

Other methods I found are the fetch API which is no better than the file reader in terms of hack rating and Blob.prototype.arrayBuffer which is not yet supported fully.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.