最近在做的一個項目中需要使用到HTML5中引入的WebSocket技術,本來以為應該很容易就能搞定,誰知道在真正上手開發了以后才發現有很多麻煩的地方,雖然我們是一個以前端開發和設計見長的團隊,而且作為一個二手程序猿又長期不被待見,但是為了讓有同樣需求的朋友少走些彎路,我還是決定把實現方法貼在這個地方。
關于WebSocket的基本概念,維基百科上解釋的很清楚,而且網上也能搜出來一大把,這里就略過不表,直接進入正題。
這次的問題首先有一個前提,就是得用Python來實現這個服務器,如果對具體語言沒有限制的話,推薦大家首選Node.js的一個第三方庫:Socket.IO,非常好用,10分鐘不打針不吃藥搞定WebSocket Server,而且用JS來寫后端,相信也能對上很多文藝開發者的胃口。
但是如果選擇用Python,google搜索的結果幾乎都不能用,最要命的問題是,WebSocket協議本身還是一個草案,所以不同瀏覽器支持的協議版本有所不同,Safari 5.1支持的是老版本協議Hybi-02,Chrome 15以及Firefox 8.0支持的是新版本協議Hybi-10,老版本協議和新版本協議在建立通信的握手方法還有數據傳輸的格式要求上都有所不同,導致網上大多數實現方式只能適用于Safari瀏覽器,并且Safari和C&F瀏覽器之間無法互相通信。
首先第一步需要解釋的是新、舊版本WebSocket協議的握手方式。我們先來看看三個不同瀏覽器發送的握手數據的結構:
Chrome:
代碼如下:
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 127.0.0.1:1337
Sec-WebSocket-Origin: http://127.0.0.1:8000
Sec-WebSocket-Key: erWJbDVAlYnHvHNulgrW8Q==
Sec-WebSocket-Version: 8
Cookie: csrftoken=xxxxxx; sessionid=xxxxx
Firefox:
代碼如下:GET / HTTP/1.1
Host: 127.0.0.1:1337
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:8.0) Gecko/20100101 Firefox/8.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive, Upgrade
Sec-WebSocket-Version: 8
Sec-WebSocket-Origin: http://127.0.0.1:8000
Sec-WebSocket-Key: 1t3F81iAxNIZE2TxqWv+8A==
Cookie: xxx
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Safari:
代碼如下:GET / HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: 127.0.0.1:1337
Origin: http://127.0.0.1:8000
Cookie: sessionid=xxxx; calView=day; dayCurrentDate=1314288000000
Sec-WebSocket-Key1: cV`p1* 42#7 ^9}_ 647 08{
Sec-WebSocket-Key2: O8 415 8x37R A8 4
;"######
可以看出,Chrome和Firefox實現的是新版協議,因此只傳輸了一個”Sec-WebSocket-Key”頭以供服務端生成握手Token,但是遵循老版本的Safari的數據中有兩個Key:”Sec-WebSocket-Key1″和”Sec-WebSocket-Key2″,因此服務端在生成握手Token的時候,需要做一次判斷。先來看使用老版本協議的Safari,Token生成算法如下:
新聞熱點
疑難解答