零距離接觸websocket

來源 | https://juejin.im/post/6876301731966713869
什么是WebSocket
定義
關聯(lián)和區(qū)別
HTTP
HTTP是非持久的協(xié)議,客戶端想知道服務端的處理進度只能通過不停地使用 Ajax進行輪詢或者采用 long poll 的方式來,但是前者對服務器壓力大,后者則會因為一直等待Response造成阻塞 
雖然http1.1默認開啟了keep-alive長連接保持了這個TCP通道使得在一個HTTP連接中,可以發(fā)送多個Request,接收多個Response,但是一個request只能有一個response。而且這個response也是被動的,不能主動發(fā)起。 websocket雖然是獨立于HTTP的一種協(xié)議,但是websocket必須依賴 HTTP 協(xié)議進行一次握手(在握手階段是一樣的),握手成功后,數(shù)據(jù)就直接從 TCP通道傳輸,與 HTTP 無關了,可以用一張圖理解兩者有交集,但是并不是全部。 
socket
socket也被稱為套接字,與HTTP和WebSocket不一樣,socket不是協(xié)議,它是在程序層面上對傳輸層協(xié)議(可以主要理解為TCP/IP)的接口封裝。可以理解為一個能夠提供端對端的通信的調用接口(API) 對于程序員而言,其需要在 A 端創(chuàng)建一個 socket 實例,并為這個實例提供其所要連接的 B 端的 IP 地址和端口號,而在 B 端創(chuàng)建另一個 socket 實例,并且綁定本地端口號來進行監(jiān)聽。當 A 和 B 建立連接后,雙方就建立了一個端對端的 TCP 連接,從而可以進行雙向通信。WebSocekt借鑒了 socket 的思想,為 client 和 server 之間提供了類似的雙向通信機制
應用場景
Websocket握手
Websocket握手請求報文:
GET /chat HTTP/1.1Host: server.example.comUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==Sec-WebSocket-Protocol: chat, superchatSec-WebSocket-Version: 13Origin: http://example.com
Upgrade: websocketConnection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==Sec-WebSocket-Protocol: chat, superchatSec-WebSocket-Version: 13
服務器響應:
HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=Sec-WebSocket-Protocol: chat
關于Websocket
WebSocket心跳
WebSocket狀態(tài)
0: 表示正在連接 1: 表示連接成功,可以通信了 2: 表示連接正在關閉 3: 表示連接已經(jīng)關閉,或者打開連接失敗
WebSocket實踐
服務端接收發(fā)送消息
npm install express ws

//引入express 和 wsconst express = require('express');const SocketServer = require('ws').Server;//指定開啟的端口號const PORT = 3000;// 創(chuàng)建express,綁定監(jiān)聽3000端口,且設定開啟后在consol中提示const server = express().listen(PORT, () => console.log(`Listening on ${PORT}`));// 將express交給SocketServer開啟WebSocket的服務const wss = new SocketServer({ server });//當 WebSocket 從外部連接時執(zhí)行wss.on('connection', (ws) => {//連接時執(zhí)行此 console 提示console.log('Client connected');// 對message設置監(jiān)聽,接收從客戶端發(fā)送的消息ws.on('message', (data) => {//data為客戶端發(fā)送的消息,將消息原封不動返回回去ws.send(data);});// 當WebSocket的連接關閉時執(zhí)行ws.on('close', () => {console.log('Close connected');});});

客戶端接收發(fā)送消息
index.html
<html><body><script src="./index.js">script>body>html>
index.js
// 使用WebSocket的地址向服務端開啟連接let ws = new WebSocket('ws://localhost:3000');// 開啟后的動作,指定在連接后執(zhí)行的事件ws.onopen = () => {console.log('open connection');};// 接收服務端發(fā)送的消息ws.onmessage = (event) => {console.log(event);};// 指定在關閉后執(zhí)行的事件ws.onclose = () => {console.log('close connection');};


服務端定時發(fā)送
//當WebSocket從外部連接時執(zhí)行wss.on('connection', (ws) => {//連接時執(zhí)行此 console 提示console.log('Client connected');+ //固定發(fā)送最新消息給客戶端+ const sendNowTime = setInterval(() => {+ ws.send(String(new Date()));+ }, 1000);- //對message設置監(jiān)聽,接收從客戶端發(fā)送的消息- ws.on('message', (data) => {- //data為客戶端發(fā)送的消息,將消息原封不動返回回去- ws.send(data);- });//當 WebSocket的連接關閉時執(zhí)行ws.on('close', () => {console.log('Close connected');});});

多人聊天

...//當WebSocket從外部連接時執(zhí)行wss.on('connection', (ws) => {//連接時執(zhí)行此 console 提示console.log('Client connected');- //固定發(fā)送最新消息給客戶端- const sendNowTime = setInterval(() => {- ws.send(String(new Date()));- }, 1000);+ //對message設置監(jiān)聽,接收從客戶端發(fā)送的消息+ ws.on('message', (data) => {+ //取得所有連接中的 客戶端+ let clients = wss.clients;+ //循環(huán),發(fā)送消息至每個客戶端+ clients.forEach((client) => {+ client.send(data);+ });+ });//當WebSocket的連接關閉時執(zhí)行ws.on('close', () => {console.log('Close connected');});});



總結?


評論
圖片
表情
