最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

node.js基于socket.io快速實現(xiàn)一個實時通訊應用

 更新時間:2019年04月23日 08:54:41   作者:薄荷前端  
這篇文章主要介紹了node.js基于socket.io快速實現(xiàn)一個實時通訊應用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

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

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

WebSocket技術應運而生。

WebSocket概念

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

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

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

實現(xiàn)

原生實現(xiàn)

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

建立連接

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

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

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

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

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

Socket.onopen = function(evt) {};

如果連接失敗,發(fā)送、接收數(shù)據(jù)失敗或者處理數(shù)據(jù)出現(xiàn)錯誤,browser會觸發(fā)onerror消息。

Socket.onerror = function(evt) { };

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

Socket.onclose = function(evt) { };

收發(fā)消息

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

Socket.onmessage = function(evt) { };

send用于向服務端發(fā)送消息。

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 協(xié)議。在低版本的瀏覽器中,不支持Websocket,為了兼容使用長輪詢(polling)替代。

API文檔

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

建立連接

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

消息收發(fā)

一、發(fā)送數(shù)據(jù)

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

二、接收數(shù)據(jù)

 socket.on(自定義發(fā)送的字段, 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.服務端發(fā)送的消息有分類,不同的客戶端需要接收的分類不同;2.服務端并不需要對所有的客戶端都發(fā)送消息,只需要針對某個特定群體發(fā)送消息;

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

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

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);
    // 向所有用戶發(fā)送消息
    io.sockets.to(data).emit("recive message", "hello,房間中的用戶");   
  }

用socket.io實現(xiàn)一個實時接收信息的例子

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

服務端

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

安裝依賴

npm install --Dev express
npm 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('連接成功');
    //連接成功之后發(fā)送消息
    socket.emit("new message", { mess: `初始消息` });
    
  });

客戶端

核心代碼——index.html(向服務端發(fā)送數(shù)據(jù))

 <div>發(fā)送信息</div>
  <input placeholder="請輸入要發(fā)送的信息" />
  <button onclick="postMessage()">發(fā)送</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(從服務端接收數(shù)據(jù))

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

效果

實時通訊效果

客戶端全部斷開連接

某客戶端斷開連接

namespace應用

加入房間

離開房間

框架中的應用

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協(xié)議

Headers

請求包

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

請求數(shù)據(jù)

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

Frames

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

其中幀數(shù)據(jù)前的數(shù)字代表什么意思呢?

這是 Engine.io協(xié)議,其中的數(shù)字是數(shù)據(jù)包編碼:

<Packet type id> [<data>]

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

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

2 ping——由客戶端發(fā)送。服務器應該用包含相同數(shù)據(jù)的乓包應答

客戶端發(fā)送:2probe探測幀

3 pong——由服務器發(fā)送以響應ping數(shù)據(jù)包。

服務器發(fā)送:3probe,響應客戶端

4 message——實際消息,客戶端和服務器應該使用數(shù)據(jù)調(diào)用它們的回調(diào)。

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

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

實例

以上的截圖是上述例子中數(shù)據(jù)傳輸?shù)膶嵗?,分析一下大概過程就是:

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

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

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

參考engine.io-protocol

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • NodeJs 實現(xiàn)簡單WebSocket即時通訊的示例代碼

    NodeJs 實現(xiàn)簡單WebSocket即時通訊的示例代碼

    這篇文章主要介紹了NodeJs 實現(xiàn)簡單WebSocket即時通訊的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • 詳解NodeJS框架express的路徑映射(路由)功能及控制

    詳解NodeJS框架express的路徑映射(路由)功能及控制

    這篇文章主要介紹了詳解NodeJS框架express的路徑映射(路由)功能及控制,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • mongoose中利用populate處理嵌套的方法

    mongoose中利用populate處理嵌套的方法

    這篇文章主要給大家介紹了關于mongoose中利用populate處理嵌套的方法,文中通過示例代碼介紹的非常詳細,對大家具有一的參考學習價值,需要的朋友們下面來一起看看吧。
    2017-05-05
  • 使用node.js實現(xiàn)接口步驟詳細記錄

    使用node.js實現(xiàn)接口步驟詳細記錄

    這篇文章主要給大家介紹了關于使用node.js實現(xiàn)接口步驟的相關資料,對于剛開始不會node寫接口和調(diào)用接口,可以通過這個清晰的初步了解到整個過程,下面需要的朋友可以參考下
    2023-03-03
  • 解析Node.js基于模塊和包的代碼部署方式

    解析Node.js基于模塊和包的代碼部署方式

    這篇文章主要介紹了解析Node.js基于模塊和包的代碼部署方式,作為一個服務于本地操作系統(tǒng)的JavaScript解釋器,Node采用了簡潔的基于模塊和包概念的部署方式,需要的朋友可以參考下
    2016-02-02
  • 從零開始學習Node.js系列教程五:服務器監(jiān)聽方法示例

    從零開始學習Node.js系列教程五:服務器監(jiān)聽方法示例

    這篇文章主要介紹了Node.js服務器監(jiān)聽方法,結合實例形式分析了nodejs事件監(jiān)聽相關操作技巧,需要的朋友可以參考下
    2017-04-04
  • Node.js模塊化的使用詳細介紹

    Node.js模塊化的使用詳細介紹

    nodejs中的模塊化是指將每個js文件會被認為單獨一個的模塊。模塊之間是互相不可見的。如果一個模塊需要使用另一個模塊,那么需要通過指定語法來引入要使用的模塊,而且只能使用引入模塊所暴露的內(nèi)容
    2022-08-08
  • Node.js原理阻塞和EventEmitter及其繼承的運用實戰(zhàn)

    Node.js原理阻塞和EventEmitter及其繼承的運用實戰(zhàn)

    這篇文章主要介紹了Node.js原理阻塞和EventEmitter及其繼承的運用實戰(zhàn),文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • Node.js中的文件系統(tǒng)(file system)模塊詳解

    Node.js中的文件系統(tǒng)(file system)模塊詳解

    Node.js文件系統(tǒng)模塊提供了豐富的方法,用于讀取、寫入、操作文件和目錄,文件系統(tǒng)模塊是Node.js強大而靈活的一部分,為文件操作提供了方便的API,本文給大家介紹Node.js中的文件系統(tǒng)(file system)模塊,感興趣的朋友一起看看吧
    2023-11-11
  • koa router 多文件引入的方法示例

    koa router 多文件引入的方法示例

    這篇文章主要介紹了koa router 多文件引入的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-05-05

最新評論

建宁县| 通海县| 达日县| 漯河市| 胶南市| 五台县| 永福县| 西青区| 双牌县| 定州市| 马关县| 遵化市| 黄梅县| 汉阴县| 新疆| 富锦市| 龙川县| 安平县| 新巴尔虎右旗| 江川县| 合山市| 仁布县| 海晏县| 承德县| 广西| 河东区| 调兵山市| 东乡县| 彭州市| 郑州市| 团风县| 平塘县| 高青县| 墨江| 天峨县| 桓台县| 绵阳市| 应用必备| 贵德县| 高阳县| 大同县|