2011-09-29 53 views
5

我有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中啓用它),所以我無法檢查其他任何內容。

回答

4

嗯,我發現這個問題。第一兩個鍵意在被級聯爲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 

隨着該鉻接受連接。我已經提交了一個錯誤,抱怨缺少錯誤消息和不正確的散列。