成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

利用socket.io實現消息實時推送

開發 前端
最近在寫的項目中存在著社交模塊,需要實現這樣的一個功能:當發生了用戶被點贊、評論、關注等操作時,需要由服務器向用戶實時地推送一條消息。最終完成的項目地址為:socket-message-push,這里將介紹一下實現的思路及部分代碼。

項目背景介紹

最近在寫的項目中存在著社交模塊,需要實現這樣的一個功能:當發生了用戶被點贊、評論、關注等操作時,需要由服務器向用戶實時地推送一條消息。最終完成的項目地址為:socket-message-push,這里將介紹一下實現的思路及部分代碼。

項目的流程中存在著這樣的幾個對象:

  • 用 Java 實現的后端服務器
  • 用 Node.js 實現的消息推送服務器
  • 用戶進行操作的客戶端

事件處理的流程如下:

  1. 用戶進行點贊操作時,后端服務器會進行處理,并向 Node.js 消息推送服務器發送一條消息
  2. Node.js 消息推送服務器接收到后端發送的消息后,處理數據,并確定向哪個用戶進行推送
  3. 用戶的客戶端接收到由 Node.js 服務器推送來的消息后,即可進行通知的顯示。

上面的流程中,Java 后端服務器是如何實現的不在此篇文章的討論范圍內,本文將主要介紹如何使用 Node.js 來實現這個消息推送服務器。

考慮消息推送服務器上必須記錄下當前在線用戶的信息,這樣才能向特定的用戶推送消息。所以當用戶登錄時,必須將自身的用戶信息發到 Node.js 服務器上。為了達到這種雙向的實時消息傳遞,很明顯地考慮用 WebSocket 來實現。既然我們在消息推送服務器上使用了 Node.js,我們就有了一個很方便的選項:socket.io。

Socket.io 介紹

Socket.io是一個用 JavaScript 實現的實時雙向通信的庫,利用它來實現我們的功能會很簡單。

socket.io 包含兩個部分:

  • 服務器端(server):運行在 Node.js 服務器上
  • 客戶端(client):運行在瀏覽器中

可以看看如下的 socket.io 的示例代碼,它給出了 socket.io 發出及監聽事件的基本用法:

  1. io.on('connection'function(socket){ 
  2.   socket.emit('request', /* */); // emit an event to the socket 
  3.   io.emit('broadcast', /* */); // emit an event to all connected sockets 
  4.   socket.on('reply'function(){ /* */ }); // listen to the event 
  5. });  

關于 Socket.io 還有一點需要注意:Socke.io 并不完全是 WebSocket 的實現。

  1. Note: Socket.IO is not a WebSocket implementation. Although Socket.IO indeed uses WebSocket as a transport when possible, it adds some metadata to each packet: the packet type, the namespace and the ack id when a message acknowledgement is needed. 

接下來我們需要用 Express.js 來建立一個服務器端程序,并在其中引入 Socket.io。

Node.js 服務器的搭建

利用 Express.js 搭建基礎服務器

我們使用了 Express.js 來搭建 Node.js 消息推送服務器,先利用一個簡要的例子來瀏覽其功能:

  1. // server.js 
  2. const express = require('express'); 
  3. const app = express(); 
  4. const path = require('path'); 
  5. const http = require('http').Server(app); 
  6.  
  7. const port = 4001; 
  8.  
  9. app.use(express.static(path.join(__dirname, 'public'))); 
  10.  
  11. app.get('/'function(req, res) { 
  12.     res.sendFile(__dirname + '/public/index.html'); 
  13. }); 
  14.  
  15. app.get('/api'function(req, res) { 
  16.     res.send('.'); 
  17. }); 
  18.  
  19. http.listen(port, function() { 
  20.     console.log(`listening on port:${port}`); 
  21. });  

將上面的代碼保存為 server.js,新建一個 public 文件夾,在其中放入 index.html 文件。運行以下命令:

  1. node server.js 

現在即可在 localhost:4001 查看效果了。

引入 Socket.io

現在已經有了一個基礎的 Express 服務器,接下來需要將 Socket.io 加入其中。

  1. const io = require('socket.io')(http); 
  2.  
  3. io.on('connection'function(socket) { 
  4.     console.log('a user connected'); 
  5.     socket.broadcast.emit('new_user', {}); 
  6.  

這里的 io 監聽 connection 事件,當 client 與 server 建立了連接之后,這里的回調函數會被調用(client 中的代碼將在下一節介紹)。

函數的參數 socket 代表的是當前的 client 和 server 間建立的這個連接。可在 client 程序中將這個建立的 socket 連接打印出來,如下圖所示:

 

其中的 id 屬性可以用于標識出這一連接,從而 server 可以向特定的用戶發送消息。

  1. socket.broadcast.emit('new_user', {}); 

這一行代碼表示 socket 將向當前所有與 server 建立了連接的 client(不包括自己) 廣播一條名為 new_user 的消息。

后端推送消息的處理流程

  1. 在 Node 服務器建立一個用戶信息和 socket id 的映射表,因為同一用戶可能打開了多個頁面,所以他的 socket id 可能存在多個值。當用戶建立連接時,往其中添加值;用戶斷開連接后,刪除相應值。
  2. 當 Java 后臺存在需要推送的消息時,會向 Node 服務器的 /api 路徑 post 一條消息,其中包括用于標識用戶的 tokenId 和其它數據。
  3. Node 服務器接收到 post 請求后,對請求內容進行處理。根據 tokenId 找出與該用戶對應的 socket id,socket.io 會根據 id 來向用戶推送消息。

對用戶信息的處理

方便起見,這里只用一個數組保存用戶信息,實際工作中可以根據需要放入數據庫中保存。

  1. global.users = []; // 記錄下登錄用戶的tokenId, socketId 

當用戶登錄時,client 會向 server 發送 user_login 事件,服務器接收到后會做如下操作:

  1. socket.on('user_login'function(info) { 
  2.     const { tokenId, userId, socketId } = info; 
  3.     addSocketId(users, { tokenId, socketId, userId }); 
  4. });  

addSocketId() 會向 users 數組中添加用戶信息,不同用戶通過 tokenId 進行區分,每個用戶有一個 socketIds 數組,保存可能存在的多個 socketId。該函數的具體代碼可見 src/utils.js 文件。

同理,還有一個 deleteSocketId() 函數用于刪除用戶信息,代碼可見同一文件。

在獲取了用戶的 tokenId 之后,就需要找到對應的 socketId,然后向特定用戶推送消息。

  1. // 只向 id = socketId 的這一連接發送消息  
  2. io.sockets.to(socketId).emit('receive_message', { 
  3.     entityType, 
  4.     data 
  5. });  

服務器的思路大致如此,接下來介紹客戶端中是如何進行相應的處理的。

客戶端

Socket.io 的初始化

首先在 html 文件中引入 Socket.io 的 client 端文件,例如通過 CDN 引入:

  1. <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script> 

其它的引入方式:

  1. <script src="/socket.io/socket.io.js"></script> 
  1. const io = require('socket.io-client'); 
  2.  
  3. // or with import syntax 
  4.  
  5. import io from 'socket.io-client' 

引入 Socket.io 后就獲得了 io 函數,通過它來與消息推送服務器建立連接。

  1. // 假設你將 Node 服務器部署后的地址為:https://www.example.com/ws 
  2. // 則: WS_HOST = 'https://www.example.com' 
  3. const msgSocket = io(`${WS_HOST}`, { 
  4.     secure: true
  5.     path: '/ws/socket.io' 
  6. });  

如果監聽本地:

  1. const msgSocket = io('http://localhost:4001'); 

這里如果寫成 io('https://www.example.com/ws') 會出現錯誤,需要將 /ws 寫入path中。

為了能在其它文件使用這一變量,可將 msgSocket 作為一個全局變量:

  1. window.msgSocket = msgSocket; 

用戶建立連接

  1. // 用戶登錄時,向服務器發送用戶的信息。服務器會在收到信息后建立 socket 與用戶的映射。 
  2. msgSocket.emit('user_login', { 
  3.     userId, 
  4.     socketId: msgSocket.id, 
  5.     tokenId 
  6. });  

接收到推送的消息后的處理

  1. // WebSocket 連接建立后,監聽名為 receive_message 的事件  
  2. msgSocket.on('receive_message', msg => { 
  3.     store.dispatch({ 
  4.         type: 'NEW_SOCKET_MSG'
  5.         payload: msg 
  6.     }); 
  7. }); 

 

當 WebSocket 服務器向客戶端推送了消息之后,客戶端需要監聽 receive_message 事件,接收到的參數中有相應待處理的信息。

由于使用了 Redux 進行數據的處理,所以這里 dispatch 了一個 NEW_SOCKET_MSG action,后續則是常規的 redux 處理流程了。

項目的使用

GitHub 上的項目地址:socket-message-push

  1. npm run dev 

即可在 devlopment 環境下進行測試,現在你就有了一個運行在4001端口的消息推送服務器了。

但是這里并沒有后端的服務器來向我們發送消息,所以我們將利用 Postman 來模擬發送消息。

為了展示程序的功能,在項目的 client 文件夾下放置了一個 index.html 文件。注意這個文件并不能用在實際的項目中,只是用來顯示消息推送的效果而已。

在開啟了服務器之后,打開 client/index.html,根據提示隨意輸入一個 tokenId 即可。

現在利用 Postman 向 localhost:4001/api post 如下的一條信息:

  1. {  
  2.     // tokens 數組表示你想向哪個用戶推送消息 
  3.     "tokens": ["1""2"],  
  4.     "data""You shall not pass!!!" 

 

至此,如果一切順利,你應該能夠在 client 的控制臺中看到收到的消息了。

 

你可以打開多個 client 頁面,輸入不同的 tokenId,然后檢查消息是否發送給了正確的用戶。

參考資料

 

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2019-07-26 14:40:58

Vue.jsSocket.IO前端

2014-07-22 10:29:04

背包算法coffee

2013-10-23 17:17:31

Node.jsdoT

2013-04-09 12:18:45

socket.ioC服務器

2023-09-19 15:33:50

Web實時消息推送

2024-09-02 09:31:19

2024-04-07 09:41:18

SignalR實時通信開發

2022-06-13 07:33:57

socketReact組件

2024-06-07 07:54:00

Solana框架區塊鏈

2015-07-15 12:53:05

Node.jsSocket.io遠程控制

2024-10-11 11:32:22

Spring6RSocket服務

2022-07-30 10:08:06

MQTT?協議物聯網

2016-11-22 13:25:28

Apache Spar大數據

2012-08-01 14:16:27

IBMdW

2014-06-10 13:54:05

Node.jsSocket.IOWebSocket

2013-05-17 15:34:45

2009-07-23 10:25:39

WCF的Duplex服

2021-02-05 07:28:11

SpringbootNettyWebsocke

2023-12-13 09:45:49

模型程序

2025-06-26 04:10:00

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩一区二区在线观看视频 | 国产伦精品一区二区三区高清 | 亚洲成网 | 亚洲欧洲精品成人久久奇米网 | www日本高清 | 久久久久久看片 | 亚洲国产精品视频 | 成人国产精品色哟哟 | 欧美三级在线 | 六月成人网| 91精品在线看| 黄色大全免费看 | 婷婷综合 | 91久久| 中文字幕亚洲视频 | 91就要激情 | 欧美日韩成人 | 欧美综合国产精品久久丁香 | 亚洲成人一区二区 | av在线二区 | 天堂在线免费视频 | 国产精品久久久久久久久久妇女 | 精品免费看| 一区二区av | 国产探花在线观看视频 | 欧美国产视频 | 国产精品婷婷 | 美女二区| 欧美在线激情 | 亚洲福利一区二区 | 欧美成人综合 | 综合久 | 中国av在线免费观看 | 日韩在线国产 | 国产精品欧美一区二区三区不卡 | 久久一区二区视频 | 欧美日韩精品久久久免费观看 | japanhd美女动 | 中文字幕在线免费观看 | 精品无码久久久久久国产 | 亚洲成人中文字幕 |