WebSocket 协议二进制数据字节序

WebSocket protocol binary data endianness

本文关键字:字节 数据 二进制 协议 WebSocket      更新时间:2023-09-26

我正在编写基于WebSocket协议的服务器和客户端。

服务器是使用Python和Twisted制作的。

现在我可以将二进制数据从服务器发送到客户端并返回,唯一的问题是,根据某些来源,从浏览器发送的二进制数据的字节序基于机器字节序。我想确定,这是真的吗?

如果这是真的,那么我是否应该以某种方式检查客户端具有的字节序并使用他的字节序从他那里读取/发送数据?检查客户端字节序的最佳方法是什么,只需从客户端发送

var view_buffer = new UInt8Array(new ArrayBuffer(1));
view_buffer[0] = 1;

此数据,并在服务器上检查它是否返回 1 或 128?

根据 RFC 6455

多字节长度数量以网络字节顺序表示。

网络字节顺序是大端序。服务器和客户端都应使用此字节顺序,无论它们的本机顺序是什么。

在 Python 中,struct 模块可用于确保与'>'说明符的正确字节顺序。我不确定如何在Javascript中完成它。

要检查字节数,您需要至少发送一个两个字节的值。

您不能仅通过发送单个字节来检查,因为此时已经为您整理了位级字节序。

因此,字节

序仅对字节交换(如果需要)以及尝试使用特定于字节序的规则打包单个位(例如在 C 中使用位域时)而言。

如果您的问题与您自己在 WebSocket 有效负载中携带的消息有关,通常的过程是自己选择一个字节顺序,然后执行您必须执行的任何打包或解压缩,以从本机字节顺序转换为您喜欢的字节顺序。 我知道的大多数协议都使用大端序,也就是"网络秩序"。

因此,如果您有一个 16 位值,请使用移位和按位运算符自行将其转换为两个 8 位字节,然后先发送顶部字节,然后发送第二个字节。 在服务器端,反向该过程。 大多数服务器端语言使得从网络顺序到本机字节顺序的字节交换值变得非常容易。

Endianess 仅与由多个字节组成的数据类型相关。由于您正在使用uint8 endianess数组并不重要。

在 RFC 6455 中,有以下关于关闭消息顺序的注释:

如果有正文,则主体的前两个字节必须是一个 2 字节无符号整数(按网络字节顺序),表示第 7.4 节中定义的值为/code/的状态代码。

因此,如果要在WS消息中使用二进制数据,听起来该协议通常希望您使用大端序。我想这不是强制性的,通过。

如果您想允许其中任何一个,您可以在消息开头添加一个幻数。这将是 2 个不同的字节,例如 (('M' <<8) |"G")。如果你收到"M"然后是"G",它是大端序。如果你收到"G"然后是"M",它是小端序。现在,每条消息都会告诉您其字节序。不再有猜测工作。

正如 Mark Ransom 在评论中指出的那样,可以从 JavaScript 以任一字节序发送数据,但是必须交换所有字节可能会很烦人。因此,具有指示当前字节序的 2 字节值通常是解决问题的非常好的解决方案。接收数据的服务器可以检查这两个字节,并相应地交换短整型、整型、整型、整型整型数据。

让客户端向服务器发送 126 字节或更多(但小于 65535)(例如 200)的文本消息。Payload_Length字段将为 126。

然后检查扩展有效负载长度的下一个两个字节,以确定客户端是以大端序(可能)发送的,还是客户端搞砸了并以小端格式发送。

对于大字节序,8 位有效负载长度旁边的字节(应为 126,表示接下来的两个字节实际包含实际有效负载长度)应该是 16 位长度的最高有效字节。