我正在编写一个小型 WebSocket 服务器应用程序,它应该支持 draft 17 和旧版本,例如 草稿 00。我对最新的草稿没有任何问题,但我无法让草稿 00 的客户满意。
出于测试目的,我使用了官方(旧)draft 00 docuemnt,第 7 页:
Sec-WebSocket-Key1: 18x 6]8vM;54 *(5: { U1]8 z [ 8
Sec-WebSocket-Key2: 1_ tx7X d < nw 334J702) 7]o}` 0
Tm[K T2u
通过连接数字并除以空格数来计算键时,我得到以下两个整数:155712099 和173347027(文档中也有这两个号码)。
接下来,它表示:
- 将它们单独转换为 Big Endian
- 将结果连接到字符串中并附加最后八位 (
Tm[K T2u
)。
- 从步骤 1 和 2 中生成的字符串创建 128 位 MD5 和。
有了这些知识,我生成了以下代码:
#define BYTE 8
#define WORD 16
// Little Endian to Big Endian short
#define LE_TO_BE_SHORT(SHORT)\
(((SHORT >> BYTE) & 0x00FF) | ((SHORT << BYTE) & 0xFF00))
// Little Endian to Big Endian long
#define LE_TO_BE_LONG(LONG)\
(((LE_TO_BE_SHORT(LONG >> WORD)) | \
((LE_TO_BE_SHORT((LONG & 0xFFFF)) << WORD))))
uint num1 = LE_TO_BE_LONG(155712099);
uint num2 = LE_TO_BE_LONG(173347027);
QString cookie = QString::fromUtf8("Tm[K T2u");
QString c = QString::number(num1) + QString::number(num2) + cookie;
QByteArray data = c.toUtf8();
qDebug() << QCryptographicHash::hash(data, QCryptographicHash::Md5);
这是我得到的:
←→»α√r¼??┐☺║Pa♠µ
这是预期的(再次基于草稿示例)
fQJ,fN/4F4!~K~MH
在另一边,我注意到 wikipedia 文章 没有提及任何有关 Endian 转换的内容。我在没有转换的情况下尝试了上面的代码(维基百科示例和草稿中的示例),但仍然无法重现预期结果。
任何人都可以指出这里有什么问题吗?
编辑:
我发现此文档对协议。它是不同的草案 (76),但在握手方面与 00 类似。
I am writing a small WebSocket server application that should support both draft 17 and older variations such as draft 00. I didn't have any problems with the newest draft, but I cannot make the draft 00 client happy.
For testing purposes I used the example provided in the official (old) draft 00 docuemnt, page 7:
Sec-WebSocket-Key1: 18x 6]8vM;54 *(5: { U1]8 z [ 8
Sec-WebSocket-Key2: 1_ tx7X d < nw 334J702) 7]o}` 0
Tm[K T2u
When calculating the keys by concatenating the digits and dividing by spaces count, I get the following two integers: 155712099 and 173347027 (the document has these two numbers as well).
Next, it says to:
- Convert them individually to Big Endian
- Concatenate the result in a string and append the last eight bits (
Tm[K T2u
).
- Create a 128 bits MD5 sum from the string produced in step 1 and 2.
Armed with this knowledge I've produced the following code:
#define BYTE 8
#define WORD 16
// Little Endian to Big Endian short
#define LE_TO_BE_SHORT(SHORT)\
(((SHORT >> BYTE) & 0x00FF) | ((SHORT << BYTE) & 0xFF00))
// Little Endian to Big Endian long
#define LE_TO_BE_LONG(LONG)\
(((LE_TO_BE_SHORT(LONG >> WORD)) | \
((LE_TO_BE_SHORT((LONG & 0xFFFF)) << WORD))))
uint num1 = LE_TO_BE_LONG(155712099);
uint num2 = LE_TO_BE_LONG(173347027);
QString cookie = QString::fromUtf8("Tm[K T2u");
QString c = QString::number(num1) + QString::number(num2) + cookie;
QByteArray data = c.toUtf8();
qDebug() << QCryptographicHash::hash(data, QCryptographicHash::Md5);
Here's what I get:
←→»α√r¼??┐☺║Pa♠µ
And here's what's expected (again, based on the draft example)
fQJ,fN/4F4!~K~MH
On the other side, I've noticed that the wikipedia article does not mention anything about Endian conversion. I tried the above code without conversion (both wikipedia example and the example from the draft) and still cannot reproduce the expected result.
Anyone can point out what is the problem here?
EDIT:
I found this document has a better explanation of the protocol. It is a different draft (76) but is similar to 00 in terms of handshake.
发布评论
评论(2)
这里是websockify。我知道这是可行的,因此您可以将其用作参考。
Here is the calculation in the C implementation of websockify. I know that works so you might be able to use that as reference.
最后,在同事们的帮助下,我明白了自己做错了什么。基本上,我实际上是将两个整数连接成一个字符串。相反,我需要连接字节:
确保您不使用不占用大小的重载构造函数,因为 Qt 会创建一个稍大的数组,并用垃圾填充。至少我的情况是这样。
Finally with the help of fresh eyes from my colleagues, I figured out what I was doing wrong. Basically I was literally concatenating the two integers into a string. Instead I needed to concatenate the bytes:
Make sure that you don't use the overloaded constructor that does not take the size because Qt will crate a slightly larger array padded with garbage. At least that was in my case.