WebSocket的總結(jié)

最近做的幾個(gè)項(xiàng)目都用到了HTML5的WebSocket技術(shù),并且在一些公司的面試中該內(nèi)容也會(huì)被問(wèn)到,為此有必要將WebSocket方面的知識(shí)整理一下。

WebSocket概述

HTTP協(xié)議是一種無(wú)狀態(tài)的協(xié)議,要實(shí)現(xiàn)有狀態(tài)的會(huì)話(huà)必須借助一些外部機(jī)制如session和cookie,這或多或少會(huì)帶來(lái)一些不便,尤其是服務(wù)端和客戶(hù)端需要實(shí)時(shí)交換數(shù)據(jù)的時(shí)候(監(jiān)控,聊天),這個(gè)問(wèn)題更加明顯。WebSocket就是在這種大環(huán)境下應(yīng)運(yùn)而生。
WebSocket允許服務(wù)器和客戶(hù)端進(jìn)行全雙工通信,傳統(tǒng)的HTTP是單雙工通信,它只能允許客戶(hù)端向服務(wù)器發(fā)出請(qǐng)求,服務(wù)端被動(dòng)返回?cái)?shù)據(jù),而不能主動(dòng)向客戶(hù)端傳遞數(shù)據(jù)。
WebSocket可以完全取代Ajax,用來(lái)向服務(wù)器傳遞字符串,二進(jìn)制等多種類(lèi)型的數(shù)據(jù),而且還不存在跨域問(wèn)題。
WebSocket不使用HTTP協(xié)議,而是使用自己的協(xié)議。瀏覽器發(fā)出的WebSocket請(qǐng)求類(lèi)似下面這種:

websocket-request.png

下面我們來(lái)分析一下這個(gè)請(qǐng)求頭部

  • Accept-Encoding:瀏覽器可以接受的數(shù)據(jù)的壓縮類(lèi)型。
  • Accept-Language:瀏覽器可以接受的語(yǔ)言類(lèi)型。
  • Cache-Control:no-cache不使用強(qiáng)緩存。
  • Connection:Upgrade 通知服務(wù)器通信協(xié)議提升。
  • Host:主機(jī)名。
  • Origin:用于驗(yàn)證瀏覽器域名是否在服務(wù)器許可范圍內(nèi)。
  • Pragma:no-cache HTTP/1.0定義的不使用本地緩存。
  • Upgrade:websocket 使用websocket協(xié)議進(jìn)行傳輸數(shù)據(jù),而不使用HTTP/1.1。
  • User-Agent:用戶(hù)代理字符串。
  • Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
  • Sec-WebSocket-Key:lb69kw8CsB4CrSk9tKa3+g== 握手協(xié)議密鑰,base64編碼的16字節(jié)的隨機(jī)字符串。
  • Sec-WebSocket-Version:13 版本號(hào)。

服務(wù)器接收到客戶(hù)端的請(qǐng)求并返回如下:

websocket-response.png

我們來(lái)分析一下服務(wù)器返回的頭部信息:

  • Connection:Upgrade 通信協(xié)議提升。
  • Upgrade: websocket 傳輸協(xié)議升級(jí)為websocket。
  • Sec-WebSocket-Extensions:permessage-deflate
  • Sec-WebSocket-Accept:q9g5u1WfIWaAjNgMmjlTQTqkS/k= 將Sec-WebSocket-Key的值進(jìn)行一定的運(yùn)算和該值進(jìn)行比較來(lái)判斷是否是目標(biāo)服務(wù)器響應(yīng)了WebSocket請(qǐng)求。

WebSocket協(xié)議用ws表示,此外還有wss表示加密的WebSocket協(xié)議,類(lèi)似https。
現(xiàn)在大部分瀏覽器都支持WebSocket(包括IE10+),服務(wù)器端(node)需要安裝模塊,目前比較流行的是socket.io和ws,我個(gè)人喜歡用ws。

客戶(hù)端該怎么用WebSocket

這里我所指的客戶(hù)端通常是指瀏覽器,而且都支持WebSocket API。你也可以通過(guò)window.WebSocket來(lái)判斷你的瀏覽器是否支持WebSocket。廢話(huà)不多說(shuō),我們先來(lái)一段代碼,然后通過(guò)代碼來(lái)學(xué)習(xí)如何在客戶(hù)端使用WebSocket。

let ws  = new WebSocket('ws://10.11.10.66:3000');
ws.addEventListener('open', event => {
        console.log(ws.readyState);
        ws.addEventListener('message', (event, flags) => {
          console.log(event.data);
              ws.send('ssss');
    });
    ws.addEventListener('close', event => {
            console.log('client notified websocket has closed', event.data);
    });
});
ws.addEventListener('error', event => {
        console.log('error', event.data);
});

接下來(lái)我們重點(diǎn)說(shuō)一下怎么使用瀏覽器WebSocketAPI。首先我們要?jiǎng)?chuàng)建一個(gè)WebSocket的實(shí)例即new WebSocket(url); 然后我們需要綁定四個(gè)事件open,message,error,close看他們的
的名字我們就知道他們表示什么意思了。發(fā)送數(shù)據(jù)使用send方法,該方法除了可以發(fā)送字符串以外還可以發(fā)送blob和二進(jìn)制數(shù)據(jù),具體怎么使用,等到大家想用的時(shí)候再去找。哦,還有一個(gè)我們創(chuàng)建好的ws對(duì)象有一個(gè)readyState屬性,它的取值有0,1,2,3分別表示正在連接,連接成功,正在關(guān)閉,連接關(guān)閉。

服務(wù)器端該怎么使用WebSocket

服務(wù)器端使用WebSocket需引入相關(guān)的模塊,目前比較流行的是socket.io和ws。由于本人在項(xiàng)目中都是使用的ws模塊,下面只給出ws模塊的使用方法,socket.io模塊的使用方法大家可以去網(wǎng)上找。

var express = require('express');
var http = require('http');
var WebSocket = require('ws');

var app = express();
app.get('/', function(req, res, next){
        res.sendFile(__dirname + '/index.html');
});
var server = http.createServer(app);
var wss = new WebSocket.Server({ server });
wss.on('connection', function(ws){
        ws.on('message', function(message, flag){
                if (ws.readyState === WebSocket.OPEN){
                        //你的操作
                }
        });
        ws.send('something');
});
server.listen(3000, function(){
        console.log('listening on port:3000');
});

下面簡(jiǎn)單說(shuō)明一下,搭配上述服務(wù)器我還引入了express模塊,其實(shí)ws模塊是可以單獨(dú)工作的,只不過(guò)我的項(xiàng)目都是建立在express開(kāi)發(fā)框架上的,express怎么使用網(wǎng)上教程也蠻多的,大家想知道具體用法可自行百度。上面的代碼可以稱(chēng)作模板式的代碼,以后大家想搭建一個(gè)WebSocket服務(wù)的話(huà),只需復(fù)制一下,然后修改對(duì)應(yīng)的參數(shù)即可,相信有一定開(kāi)發(fā)經(jīng)驗(yàn)的同學(xué)都看得懂其中的含義。

WebSocket和Socket的區(qū)別

WebSocket和Socket有什么區(qū)別或者聯(lián)系?說(shuō)到這個(gè)我不得不用這句話(huà)來(lái)回答你:就像Java和JavaScript的關(guān)系一樣,兩者沒(méi)有絲毫的聯(lián)系。


Java和JavaScript

首先說(shuō)一下Socket,這個(gè)東西我在大學(xué)時(shí)上java 課網(wǎng)絡(luò)編程的時(shí)候就接觸過(guò),套接字,它是為了方便我們開(kāi)發(fā)人員使用TCP/IP或者UDP來(lái)構(gòu)建服務(wù)而抽象出來(lái)的一個(gè)概念,它也有自己的一套API,說(shuō)實(shí)話(huà)它是和網(wǎng)絡(luò)中的運(yùn)輸層打交道的,如果你的項(xiàng)目是基于HTTP來(lái)構(gòu)建服務(wù)的話(huà)可以不用理會(huì)它。
WebSocket則是一種新的通信協(xié)議,是為了解決實(shí)時(shí)傳遞數(shù)據(jù)而開(kāi)發(fā)的一種全雙工的通信協(xié)議,它也有自己的一套編程接口,作為開(kāi)發(fā)人員我們知道這些就足夠了,畢竟我們不是搞科學(xué)研究的,點(diǎn)到為止。

WebSocket和HTTP的比較

相同點(diǎn):

  • 都屬于應(yīng)用層的協(xié)議。
  • 都使用Request/Response模型進(jìn)行連接的建立。
  • 都可以在網(wǎng)絡(luò)中傳輸數(shù)據(jù)。

不同點(diǎn):

  • ws使用HTTP來(lái)建立連接,但是定義了一系列新的header域,這些域在HTTP中并不會(huì)使用。
  • ws連接建立之后,通信雙方都可以在任何時(shí)刻向另一方發(fā)送數(shù)據(jù)。
  • ws連接建立之后,數(shù)據(jù)的傳輸使用幀來(lái)傳遞,不再需要Request消息。
  • ws的數(shù)據(jù)幀有序。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容