我通过网络套接字从python服务器发送二进制数据:
data = struct.pack('!BI', 2, 1)
channel.send(channel.BINARY, data)
数据发送工作正常。在客户端,javascript是这样的:
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]);
这怎么会发生?字节长度减去字节偏移量为4,BYTY_ELEMENT_SIZE也是4。读取第一个值时不会出现问题,但无论它是什么类型,下一个值都会引发错误。即使我只设置像这样的字节偏移
var array2 = new Uint32Array(data,1);
出现错误。
不能创建偏移量不能被4整除的int32/uint32数组。int16/uint16和2也是如此。
这就是CPU体系结构的局限性。
设这两个变量为A:Uint16
和B:Uint8
。你可以用不同的方法将它们映射到字节上:
BBAA
(将值B放入Uint16)0BAA
/B0AA
(跳过1个字节进行对齐)AAB
(重新排序以对齐)
如果你不想考虑大/小endiad、重新排序和其他事情。。。即,如果出于某种原因,您仍然希望将变量作为BAA
放入字节中,那么请使用以下思想:
对于每个未对齐的变量,将其放入相应大小的缓冲区并逐字节复制。如果未对齐是2个字节,则可以按字节对进行复制。
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]);
顺便说一句,js:中有一些现成的打包/拆包代码
- 矿井
- phpjs
类似于php包
我的代码可能更有趣,因为有两个类:打包到二进制字符串和打包到arraybuffer。