前言
因為項目需要,前端頁面中需要不斷向后台請求獲取一個及一個以上的狀態值。最初的方案是為每個狀態值請求都建立一個定時器循環定時發起Ajax請求,結果顯而 易見。在HTTP1.1協議中,同一客戶端瀏覽器發起二個及以上請求時,服務器都會進行隊列阻塞,即前一請求個執行完后才能執行下一個請求。而在當前前端異步請求十分頻繁的情況下,一個頁面同時開始一個及以上的長輪詢,不僅服務器要承擔非常大的壓力,前端頁面也會因為輪詢的擠占而導致性能低下,用戶體驗不好。依據以上原因,曾經做過多次調研,無論是Comet技術,還是Iframe流技術,都不是很符合要求。而HTML5中新定義的Websocket協議,因為前期調研時發現沒有合適的基於C#的類庫而止步。現有的類庫基本都是基於.net Framework4.5以上,並且都是封裝好的。直到最近看到IBM上有一篇基於C#的開源Websocket應用構建,才開始再次嘗試。
(附贈相關論文地址:http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/)
握手
其實WebScoket的基本原理和Socket一樣,只不過客戶端和服務器想建立連接需要一次額外的握手。
客戶端發送內容:
GET / HTTP/1.1 Upgrade: websocket Connection: Upgrade Host: 127.0.0.1:8080 Origin: http://test.com Pragma: no-cache Cache-Control: no-cache Sec-WebSocket-Key: OtZtd55qBhJF2XLNDRgUMg== Sec-WebSocket-Version: 13 Sec-WebSocket-Extensions: x-webkit-deflate-frame User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
服務器端返回內容:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: xsOSgr30aKL2GNZKNHKmeT1qYjA=
以上需要注意的是,請求中的【Sec-WebSocket-Key】是隨機發送的。而服務器返回的【Sec-WebSocket-Accept】是將【Sec-WebSocket-Key】加上一個固定字符串【258EAFA5-E914-47DA-95CA-C5AB0DC85B11】,並使用SHA-1加密后,再進行BASE-64編碼生成的。
流程
因為本文講的是在MVC中搭建WebSocket服務,所以和很多網上介紹的聊天服務器有所差別。
以下就是WebSocket服務運行的基本流程。
與Ajax的並發阻塞測試
因為使用WebSocket的目的之一就是為了能夠避免與Ajax之間的並發線程阻塞問題,對此還進行相關的測試。
測試手段:
1.WebSocket后台每隔15秒執行兩個方法,並且這兩個方法執行期間會延遲2秒中。
2.前台Ajax連續發起10次請求,每次請求時后台會延遲4秒返回。
測試結果:
測試結論:
1.開啟WebSocket長連接后,並沒有阻塞Ajax的異步請求。也就是說在開啟WebSocket的同時,也能保證Ajax的正常運行。
2.從兩次WebSocket返回結果的時間間隔來看,Ajax的線程阻塞對WebSocket的運行沒有影響。