Question

I send binary data over websocket from python server:

data = struct.pack('!BI', 2, 1)
channel.send(channel.BINARY, data)

Data sending works fine. On client side javascript gets it like this:

onbinarydata: function(data) {
    alert(data.byteLength);
    >> 5
    var array = new Uint8Array(data,0,1);
    alert(array[0]);
    >> 2
    var array2 = new Uint32Array(data,1,5);
    >> Uncaught Error: INDEX_SIZE_ERR: DOM Exception 1
    alert(array2[0]);

How can this happen? Byte length minus byte offset is 4, and BYTY_ELEMENT_SIZE is also 4. First value is read without problems, but next always raise error, whatever type it is. Even if I only set byte offset like this

var array2 = new Uint32Array(data,1);

there is an error.

Was it helpful?

Solution

One cannot create int32/uint32 array with offset not divisible by 4. The same for int16/uint16 and 2.

This is the limitation of CPU architecture.

Let those 2 variables would be A:Uint16 and B:Uint8. You can map them onto bytes with different methods:

  • BBAA (put value B into Uint16)
  • 0BAA / B0AA (skip 1 byte for alignment)
  • AAB (reorder for alignment).

If you don't want to think about big-/little-endiad, reordering and other stuff... i.e. if you still want to put variables into bytes as BAA for some reason, then use the following idea:

For each not-aligned variable put into corresponding size buffer and copy it byte-by-byte. If misalign is 2 bytes, then copy may be made by pair of bytes.

var array = new Uint8Array(data,0,1);
alert(array);

var array2 = new Uint8Array(data,1,5);
var abuf2 = new ArrayBuffer(4);
var abuf2_8 = new Uint8Array(abuf2);
// using `subarray` won't help, cause it doesn't create a copy like `slice`
// and the same data will have the same inconsistent memory alignment
for (var i = 0; i < 4; i++) abuf2_8[i] = array2[i];
var abuf2_32 = new Uint32Array(abuf2);
alert(abuf2_32[0]);

BTW There's some ready code for packing/unpacking in js:

which are similar to php pack

My code may be more interesting to you, cause there're 2 classes: to pack into binary string and to pack into arraybuffer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top