亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

node.js基于socket.io快速實現一個實時通訊應用

2024-05-06 16:50:12
字體:
來源:轉載
供稿:網友

隨著web技術的發展,使用場景和需求也越來越復雜,客戶端不再滿足于簡單的請求得到狀態的需求。實時通訊越來越多應用于各個領域。

HTTP是最常用的客戶端與服務端的通信技術,但是HTTP通信只能由客戶端發起,無法及時獲取服務端的數據改變。只能依靠定期輪詢來獲取最新的狀態。時效性無法保證,同時更多的請求也會增加服務器的負擔。

WebSocket技術應運而生。

WebSocket概念

不同于HTTP半雙工協議,WebSocket是基于TCP 連接的全雙工協議,支持客戶端服務端雙向通信。

WebSocket使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,并進行雙向數據傳輸。

WebSocket API中,瀏覽器和服務器只需要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送。

node.js,socket.io,實時通訊應用

實現

原生實現

WebSocket對象一共支持四個消息 onopen, onmessage, onclose和onerror。

建立連接

通過javascript可以快速的建立一個WebSocket連接:

var Socket = new WebSocket(url, [protocol] );

以上代碼中的第一個參數url, 指定連接的URL。第二個參數 protocol是可選的,指定了可接受的子協議。

同http協議使用http://開頭一樣,WebSocket協議的URL使用ws://開頭,另外安全的WebSocket協議使用wss://開頭。

當Browser和WebSocketServer連接成功后,會觸發onopen消息。

Socket.onopen = function(evt) {};

如果連接失敗,發送、接收數據失敗或者處理數據出現錯誤,browser會觸發onerror消息。

Socket.onerror = function(evt) { };

當Browser接收到WebSocketServer端發送的關閉連接請求時,就會觸發onclose消息。

Socket.onclose = function(evt) { };

收發消息

當Browser接收到WebSocketServer發送過來的數據時,就會觸發onmessage消息,參數evt中包含server傳輸過來的數據。

Socket.onmessage = function(evt) { };

send用于向服務端發送消息。

Socket.send();

socket

WebSocket是跟隨HTML5一同提出的,所以在兼容性上存在問題,這時一個非常好用的庫就登場了——Socket.io。

socket.io封裝了websocket,同時包含了其它的連接方式,你在任何瀏覽器里都可以使用socket.io來建立異步的連接。socket.io包含了服務端和客戶端的庫,如果在瀏覽器中使用了socket.io的js,服務端也必須同樣適用。

socket.io是基于 Websocket 的Client-Server 實時通信庫。

socket.io底層是基于engine.io這個庫。engine.io為 socket.io 提供跨瀏覽器/跨設備的雙向通信的底層庫。engine.io使用了 Websocket 和 XHR 方式封裝了一套 socket 協議。在低版本的瀏覽器中,不支持Websocket,為了兼容使用長輪詢(polling)替代。

node.js,socket.io,實時通訊應用

API文檔

Socket.io允許你觸發或響應自定義的事件,除了connect,message,disconnect這些事件的名字不能使用之外,你可以觸發任何自定義的事件名稱。

建立連接

  const socket = io("ws://0.0.0.0:port"); // port為自己定義的端口號  let io = require("socket.io")(http);  io.on("connection", function(socket) {})

消息收發

一、發送數據

socket.emit(自定義發送的字段, data);

二、接收數據

 socket.on(自定義發送的字段, function(data) {    console.log(data);  })

斷開連接

一、全部斷開連接

  let io = require("socket.io")(http);  io.close();

二、某個客戶端斷開與服務端的鏈接

  // 客戶端  socket.emit("close", {});
 // 服務端  socket.on("close", data => {    socket.disconnect(true);  });

room和namespace

有時候websocket有如下的使用場景:1.服務端發送的消息有分類,不同的客戶端需要接收的分類不同;2.服務端并不需要對所有的客戶端都發送消息,只需要針對某個特定群體發送消息;

針對這種使用場景,socket中非常實用的namespace和room就上場了。

先來一張圖看看namespace與room之間的關系:

node.js,socket.io,實時通訊應用

namespace

服務端

  io.of("/post").on("connection", function(socket) {    socket.emit("new message", { mess: `這是post的命名空間` });  });    io.of("/get").on("connection", function(socket) {    socket.emit("new message", { mess: `這是get的命名空間` });  });

客戶端

  // index.js  const socket = io("ws://0.0.0.0:****/post");  socket.on("new message", function(data) {    console.log('index',data);  }    //message.js  const socket = io("ws://0.0.0.0:****/get");  socket.on("new message", function(data) {    console.log('message',data);  }

room

客戶端

 //可用于客戶端進入房間;  socket.join('room one');  //用于離開房間;  socket.leave('room one');

服務端

  io.sockets.on('connection',function(socket){    //提交者會被排除在外(即不會收到消息)    socket.broadcast.to('room one').emit('new messages', data);    // 向所有用戶發送消息    io.sockets.to(data).emit("recive message", "hello,房間中的用戶");     }

用socket.io實現一個實時接收信息的例子

終于來到應用的階段啦,服務端用node.js模擬了服務端接口。以下的例子都在本地服務器中實現。

服務端

先來看看服務端,先來開啟一個服務,安裝expresssocket.io

安裝依賴

npm install --Dev expressnpm install --Dev socket.io

構建node服務器

 let app = require("express")();  let http = require("http").createServer(handler);  let io = require("socket.io")(http);  let fs = require("fs");    http.listen(port); //port:輸入需要的端口號    function handler(req, res) {   fs.readFile(__dirname + "/index.html", function(err, data) {    if (err) {     res.writeHead(500);     return res.end("Error loading index.html");    }      res.writeHead(200);    res.end(data);   });  }    io.on("connection", function(socket) {    console.log('連接成功');    //連接成功之后發送消息    socket.emit("new message", { mess: `初始消息` });      });

客戶端

核心代碼——index.html(向服務端發送數據)

 <div>發送信息</div>  <input placeholder="請輸入要發送的信息" />  <button onclick="postMessage()">發送</button>
 // 接收到服務端傳來的name匹配的消息  socket.on("new message", function(data) {   console.log(data);  });    function postMessage() {   socket.emit("recive message", {    message: content,    time: new Date()   });   messList.push({    message: content,    time: new Date()   });  }

核心代碼——message.html(從服務端接收數據)

socket.on("new message", function(data) {   console.log(data);  });

效果

實時通訊效果

node.js,socket.io,實時通訊應用

客戶端全部斷開連接

node.js,socket.io,實時通訊應用

某客戶端斷開連接

node.js,socket.io,實時通訊應用

namespace應用

node.js,socket.io,實時通訊應用

加入房間

node.js,socket.io,實時通訊應用

離開房間

node.js,socket.io,實時通訊應用

框架中的應用

npm install socket.io-client
const socket = require('socket.io-client')('http://localhost:port');  componentDidMount() {    socket.on('login', (data) => {      console.log(data)    });    socket.on('add user', (data) => {      console.log(data)    });    socket.on('new message', (data) => {      console.log(data)    });  }

分析webSocket協議

Headers

node.js,socket.io,實時通訊應用

請求包

 Accept-Encoding: gzip, deflate  Accept-Language: zh-CN,zh;q=0.9,en;q=0.8  Cache-Control: no-cache  Connection: Upgrade  Cookie: MEIQIA_VISIT_ID=1IcBRlE1mZhdVi1dEFNtGNAfjyG; token=0b81ffd758ea4a33e7724d9c67efbb26; io=ouI5Vqe7_WnIHlKnAAAG  Host: 0.0.0.0:2699  Origin: http://127.0.0.1:5500  Pragma: no-cache  Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits  Sec-WebSocket-Key: PJS0iPLxrL0ueNPoAFUSiA==  Sec-WebSocket-Version: 13  Upgrade: websocket  User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1

請求包說明:

  • 必須是有效的http request 格式;
  • HTTP request method 必須是GET,協議應不小于1.1 如: Get / HTTP/1.1;
  • 必須包括Upgrade頭域,并且其值為“websocket”,用于告訴服務器此連接需要升級到websocket;
  • 必須包括”Connection” 頭域,并且其值為“Upgrade”;
  • 必須包括”Sec-WebSocket-Key”頭域,其值采用base64編碼的隨機16字節長的字符序列;
  • 如果請求來自瀏覽器客戶端,還必須包括Origin頭域 。 該頭域用于防止未授權的跨域腳本攻擊,服務器可以從Origin決定是否接受該WebSocket連接;
  • 必須包括“Sec-webSocket-Version”頭域,是當前使用協議的版本號,當前值必須是13;
  • 可能包括“Sec-WebSocket-Protocol”,表示client(應用程序)支持的協議列表,server選擇一個或者沒有可接受的協議響應之;
  • 可能包括“Sec-WebSocket-Extensions”, 協議擴展, 某類協議可能支持多個擴展,通過它可以實現協議增強;
  • 可能包括任意其他域,如cookie.

應答包

應答包說明:

 Connection: Upgrade  Sec-WebSocket-Accept: I4jyFwm0r1J8lrnD3yN+EvxTABQ=  Sec-WebSocket-Extensions: permessage-deflate  Upgrade: websocket
  • 必須包括Upgrade頭域,并且其值為“websocket”;
  • 必須包括Connection頭域,并且其值為“Upgrade”;
  • 必須包括Sec-WebSocket-Accept頭域,其值是將請求包“Sec-WebSocket-Key”的值,與”258EAFA5-E914-47DA-95CA-C5AB0DC85B11″這個字符串進行拼接,然后對拼接后的字符串進行sha-1運算,再進行base64編碼,就是“Sec-WebSocket-Accept”的值;
  • 應答包中冒號后面有一個空格;
  • 最后需要兩個空行作為應答包結束。

請求數據

 EIO: 3  transport: websocket  sid: 8Uehk2UumXoHVJRzAAAA
  • EIO:3 表示使用的是engine.io協議版本3
  • transport 表示傳輸采用的類型
  • sid: session id (String)

Frames

WebSocket協議使用幀(Frame)收發數據,在控制臺->Frames中可以查看發送的幀數據。

其中幀數據前的數字代表什么意思呢?

這是 Engine.io協議,其中的數字是數據包編碼:

<Packet type id> [<data>]

0 open——在打開新傳輸時從服務器發送(重新檢查)

1 close——請求關閉此傳輸,但不關閉連接本身。

2 ping——由客戶端發送。服務器應該用包含相同數據的乓包應答

客戶端發送:2probe探測幀

3 pong——由服務器發送以響應ping數據包。

服務器發送:3probe,響應客戶端

4 message——實際消息,客戶端和服務器應該使用數據調用它們的回調。

5 upgrade——在engine.io切換傳輸之前,它測試,如果服務器和客戶端可以通過這個傳輸進行通信。如果此測試成功,客戶端發送升級數據包,請求服務器刷新其在舊傳輸上的緩存并切換到新傳輸。

6 noop——noop數據包。主要用于在接收到傳入WebSocket連接時強制輪詢周期。

實例

node.js,socket.io,實時通訊應用

node.js,socket.io,實時通訊應用

以上的截圖是上述例子中數據傳輸的實例,分析一下大概過程就是:

  • connect握手成功
  • 客戶端會發送2 probe探測幀
  • 服務端發送響應幀3probe
  • 客戶端會發送內容為5的Upgrade幀
  • 服務端回應內容為6的noop幀
  • 探測幀檢查通過后,客戶端停止輪詢請求,將傳輸通道轉到websocket連接,轉到websocket后,接下來就開始定期(默認是25秒)的 ping/pong
  • 客戶端、服務端收發數據,4表示的是engine.io的message消息,后面跟隨收發的消息內容

為了知道Client和Server鏈接是否正常,項目中使用的ClientSocket和ServerSocket都有一個心跳的線程,這個線程主要是為了檢測Client和Server是否正常鏈接,Client和Server是否正常鏈接主要是用ping pong流程來保證的。

該心跳定期發送的間隔是socket.io默認設定的25m,在上圖中也可觀察發現。該間隔可通過配置修改。

node.js,socket.io,實時通訊應用

參考engine.io-protocol

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久综合伊人77777| 亚洲深夜福利视频| 岛国视频午夜一区免费在线观看| 久久精品国产久精国产一老狼| 国产日韩中文字幕在线| 黑人狂躁日本妞一区二区三区| 欧美色videos| 亚洲黄色av网站| 国产精品视频久久久久| 亚洲人成伊人成综合网久久久| 欧美一级在线亚洲天堂| 国产色视频一区| 国产xxx69麻豆国语对白| 97视频在线观看亚洲| 不卡在线观看电视剧完整版| 日韩性生活视频| 91精品国产高清久久久久久久久| 69久久夜色精品国产69| 亚洲一区二区中文字幕| 日韩欧美中文字幕在线播放| 日韩在线观看免费全| 亚洲欧美在线一区二区| 国产中文字幕日韩| 国产精品尤物福利片在线观看| 亚洲欧美国产制服动漫| 欧美体内谢she精2性欧美| 国产精品一区二区3区| 国产精品一二三在线| 日韩在线视频免费观看| 在线观看日韩视频| 91在线色戒在线| 美乳少妇欧美精品| 亚洲理论在线a中文字幕| 久久琪琪电影院| 亚洲欧洲在线看| 日韩美女主播视频| www日韩中文字幕在线看| 91网在线免费观看| 亚洲视频在线视频| 久久最新资源网| 亚洲电影免费观看高清完整版| 日本成人精品在线| 久久欧美在线电影| 亚洲欧洲日产国码av系列天堂| 国产精品主播视频| 成人黄色网免费| 欧美性猛交丰臀xxxxx网站| 日韩av在线天堂网| 欧美国产极速在线| www.日韩av.com| 国产丝袜视频一区| 亚洲精品一区二区久| 国产日韩在线看| 久久久久国产精品www| 日韩视频免费中文字幕| 最近2019免费中文字幕视频三| 亚洲国产免费av| 日韩免费精品视频| 日韩美女在线观看| 欧美专区国产专区| 91系列在线观看| 久久精品色欧美aⅴ一区二区| 国产精品免费观看在线| 欧美日韩国产在线| 91av在线国产| 91久久精品美女高潮| 日韩午夜在线视频| 欧美激情图片区| 久久精品一区中文字幕| 国产+成+人+亚洲欧洲| 久久久国产成人精品| 国产精品白嫩初高中害羞小美女| 亚洲精品成人久久久| 久久亚洲成人精品| 91色视频在线导航| 亚洲有声小说3d| 欧美国产极速在线| 亚洲欧洲中文天堂| 欧美激情一级二级| 国产一区二区三区丝袜| 7777免费精品视频| 精品欧美国产一区二区三区| 日韩大陆毛片av| 在线色欧美三级视频| 日本午夜精品理论片a级appf发布| 欧美最顶级丰满的aⅴ艳星| 国产一区二区三区高清在线观看| 日韩美女视频免费在线观看| 亚洲第一区中文字幕| 亚洲国产中文字幕久久网| 国产一区二区三区丝袜| 精品久久久一区二区| 亲爱的老师9免费观看全集电视剧| 色青青草原桃花久久综合| 久久理论片午夜琪琪电影网| 亚洲一区美女视频在线观看免费| 精品中文视频在线| 57pao国产成人免费| 国产精品免费一区豆花| 国产亚洲欧美日韩美女| 欧美精品videosex牲欧美| 日韩一二三在线视频播| 欧美国产亚洲精品久久久8v| 欧美又大又硬又粗bbbbb| 日韩美女在线观看一区| 日韩欧美aⅴ综合网站发布| 亚洲欧美日韩国产成人| 在线电影av不卡网址| 日韩欧美一区二区在线| 91精品国产91久久| 日韩在线视频中文字幕| 国产精品亚洲精品| 2019中文字幕在线| 国内精品视频一区| 国产成人一区二区在线| 亚洲国产精品大全| 国产日韩在线一区| 国产视频亚洲精品| 95av在线视频| 久久精品视频亚洲| 日韩美女激情视频| 欧美激情中文网| 精品欧美一区二区三区| 欧美一级bbbbb性bbbb喷潮片| 国产视频综合在线| 欧美激情奇米色| 亚洲欧美日韩爽爽影院| 性欧美长视频免费观看不卡| 美日韩精品免费视频| 国产精品视频成人| 国产精品欧美亚洲777777| 国产精品日韩在线| 久久国产精品久久久久| 成人久久久久久久| 久久九九全国免费精品观看| 欧美激情在线播放| 午夜欧美大片免费观看| 国产精品999| 久久精品中文字幕免费mv| 狠狠躁夜夜躁人人爽超碰91| 亚洲直播在线一区| 亚洲日本欧美中文幕| 日韩大片在线观看视频| 国产日韩精品一区二区| 精品久久久久久久久久| 亚洲一区www| 久久久亚洲成人| 亚洲综合中文字幕在线观看| 麻豆成人在线看| 欧美怡春院一区二区三区| 国产suv精品一区二区三区88区| 自拍亚洲一区欧美另类| 色小说视频一区| 91tv亚洲精品香蕉国产一区7ujn| 国产精品成人久久久久| 欧美激情一级欧美精品| 久久精品夜夜夜夜夜久久| 欧美福利小视频| 亚洲另类xxxx| 国产精品成久久久久三级| 亚洲国产精品人人爽夜夜爽| 欧美视频专区一二在线观看| 国产亚洲在线播放| 国产精品久久77777|