我正在编写一个小型WebSocket服务器应用程序,它应该同时支持draft 17和较早的变体,例如draft 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 (该文档也有这两个数字) )。
接下来,它说:
Tm[K T2u
)。 有了这些知识,我就制作了以下代码:
#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 article没有提及有关Endian转换的任何内容。我尝试了上面的代码而没有转换(维基百科示例和草案中的示例)仍然无法重现预期的结果。
任何人都可以指出这里的问题是什么?
编辑:
我发现this document对协议有更好的解释。这是一个不同的草案(76),但在握手方面类似于00.
答案 0 :(得分:2)
Here是websockify的C实现中的计算。我知道这样可行,所以你可以将它作为参考。
答案 1 :(得分:2)
最后,在同事的新鲜眼睛的帮助下,我弄明白自己做错了什么。基本上我真的把两个整数连成一个字符串。相反,我需要连接字节:
uint num1 = LE_TO_BE_LONG(155712099); // macros definition can
uint num2 = LE_TO_BE_LONG(173347027); // be found in the question
QString cookie = QString::fromUtf8("Tm[K T2u");
QByteArray array;
array = QByteArray((const char*)&num1, sizeof(int));
array += QByteArray((const char*)&num2, sizeof(int));
array += QByteArray(cookie.toStdString().data(), cookie.length());
qDebug() << QCryptographicHash::hash(array, QCryptographicHash::Md5);
确保您不使用不占用大小的重载构造函数,因为Qt会创建一个稍微大一些填充垃圾的数组。至少那是我的情况。