Chromium关闭WebSocket没有任何解释
问题描述:
我有Chromium 12.0.742.112(90304),我试图用它设置一个简单的WebSocket服务器。我收到一个握手请求,如:Chromium关闭WebSocket没有任何解释
Upgrade: WebSocket
Connection: Upgrade
Host: akira:22222
Origin: http://akira:22222
Sec-WebSocket-Key1: ;39LP*eC48 n /r0P6 v6548
Sec-WebSocket-Key2: 1 0 r 362547 4 4 G
后跟8个关键字节,在这种情况下是88 09 F9 EE 21 13 F4 0D。我已经验证了这些与Chromium在网络控制台选项卡中显示的密钥相同。我计算了前两个按键为:
Key1: 3948066548/4 = 987016637
Key2: 1036254744/12 = 86354562
和发送我的回应:
000001 48 54 54 50 2F 31 2E 31 20 31 30 31 20 57 65 62 HTTP/1.1 101 Web
000011 20 53 6F 63 6B 65 74 20 50 72 6F 74 6F 63 6F 6C Socket Protocol
000021 20 48 61 6E 64 73 68 61 6B 65 0D 0A 55 70 67 72 Handshake..Upgr
000031 61 64 65 3A 20 57 65 62 53 6F 63 6B 65 74 0D 0A ade: WebSocket..
000041 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 55 70 67 72 Connection: Upgr
000051 61 64 65 0D 0A 53 65 63 2D 57 65 62 53 6F 63 6B ade..Sec-WebSock
000061 65 74 2D 4F 72 69 67 69 6E 3A 20 68 74 74 70 3A et-Origin: http:
000071 2F 2F 61 6B 69 72 61 3A 32 32 32 32 32 0D 0A 53 //akira:22222..S
000081 65 63 2D 57 65 62 53 6F 63 6B 65 74 2D 4C 6F 63 ec-WebSocket-Loc
000091 61 74 69 6F 6E 3A 20 77 73 3A 2F 2F 61 6B 69 72 ation: ws://akir
0000A1 61 3A 32 32 32 32 32 2F 73 6F 63 6B 65 74 0D 0A a:22222/socket..
0000B1 0D 0A FF F4 2E 12 9D DC 12 C2 56 40 B8 09 F3 84 [email protected]
0000C1 CA EF .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..##############
铬刚刚关闭套接字,甚至没有在JS控制台打印信息。我不知道我做错了什么?
的服务器端代码是在Lua(因此为什么上面的十六进制转储被索引从1开始):
require('crypto')
local handshake = {
"HTTP/1.1 101 Web Socket Protocol Handshake",
"Upgrade: WebSocket",
"Connection: Upgrade",
"Sec-WebSocket-Origin: " .. request.header.origin,
"Sec-WebSocket-Location: " ..
request.header.origin:gsub('http:', 'ws:') .. "/socket",
'\r\n'}
log.debug("Request header:\n%s\n", table.concat(request.rawheader, '\n'))
local client = response.socket
client:settimeout(10)
local keys =
{request.header.sec_websocket_key1, request.header.sec_websocket_key2}
local sum = {}
for i, k in ipairs(keys) do
local nspc = 0
sum[i] = ''
k:gsub('%d', function(n) sum[i] = sum[i] ..n end)
k:gsub(' ', function() nspc = nspc + 1 end)
log.debug("Key%d: %s/%d = ", i, sum[i], nspc)
sum[i] = tostring(tonumber(sum[i])/nspc)
log.debug("%s\n", sum[i])
end
local key = assert(client:receive(8))
local bytes = {key:byte(1, #key)}
local keydump = {}
for i = 1, #bytes do keydump[i] = ('%02X'):format(bytes[i]) end
log.debug("Key3: %s\n", table.concat(keydump, ' '))
local resp = crypto.evp.digest('md5', table.concat(sum) .. key, true)
handshake = table.concat(handshake, '\r\n') .. resp
client:settimeout(0.1)
log.debug("Send handshake:\n%s\n", rena.debug.hexdump(handshake))
client:send(handshake)
repeat
local res, err = client:receive('*l')
if res then log.debug("R: %s\n", res) end
local res, err = client:send("Test " .. tostring(os.time()) .. '\n')
if res then socket.sleep(1)
elseif err == 'timeout' then log.debug("WS: Timed out\n")
elseif err == 'closed' then log.debug("WS: Closed\n")
else log.error("WS: Error: %s\n", tostring(err))
end
until not res
(该脚本由所述服务器的脚本,其预先设置的一些变量,如请求和装载响应,并使用LuaCrypto for MD5)。一切看起来都正确(尽管我注意到所有示例都显示了二进制密钥的好ASCII字符,而我的大多数是不可打印的),但它只是关闭套接字。
不幸的是,Chromium是我唯一一个支持WebSocket的浏览器(除非有某种方式可以在Firefox 6中启用它),所以我无法检查其他任何内容。
答
嗯,我发现这个问题。第一两个键意在被级联为32位整数(成一个单一的64位整数),而不是作为ASCII字符串:
- sum[i] = tostring(tonumber(sum[i])/nspc)
+ sum[i] = ('%08X'):format(tonumber(sum[i])/nspc)
- local resp = crypto.evp.digest('md5', table.concat(sum) .. key, true)
- handshake = table.concat(handshake, '\r\n') .. resp
+ local challenge = ''
+ (sum[1] .. sum[2]):gsub('..', function(byte)
+ challenge = challenge .. string.char(tonumber(byte, 16))
+ end)
+
+ challenge = challenge .. key
+ log.debug("Ch: %s\n", challenge:tohex())
+
+ local resp = crypto.evp.digest('md5', challenge, true)
+ handshake = table.concat(handshake, '\r\n') .. resp
随着该铬接受连接。我已经提交了一个错误,抱怨缺少错误消息和不正确的散列。