热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何使用socket.io实现消息实时推送功能

本篇文章给大家分享的是有关如何使用socket.io实现消息实时推送功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所

本篇文章给大家分享的是有关如何使用socket.io实现消息实时推送功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

Socket.io 介绍

Socket.io是一个用 Javascript 实现的实时双向通信的库,利用它来实现我们的功能会很简单。

socket.io 包含两个部分:

  • 服务器端(server):运行在 Node.js 服务器上

  • 客户端(client):运行在浏览器中

可以看看如下的 socket.io 的示例代码,它给出了 socket.io 发出及监听事件的基本用法:

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

关于 Socket.io 还有一点需要注意:Socke.io 并不完全是 WebSocket 的实现。

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 消息推送服务器,先利用一个简要的例子来浏览其功能:

// server.js const express = require('express'); const app = express(); const path = require('path'); const http = require('http').Server(app);  const port = 4001;  app.use(express.static(path.join(__dirname, 'public')));  app.get('/', function(req, res) {     res.sendFile(__dirname + '/public/index.html'); });  app.get('/api', function(req, res) {     res.send('.'); });  http.listen(port, function() {     console.log(`listening on port:${port}`); });

将上面的代码保存为 server.js,新建一个 public 文件夹,在其中放入 index.html 文件。运行以下命令:

node server.js

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

引入 Socket.io

现在已经有了一个基础的 Express 服务器,接下来需要将 Socket.io 加入其中。

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

这里的 io 监听 connection 事件,当 client 与 server 建立了连接之后,这里的回调函数会被调用(client  中的代码将在下一节介绍)。

函数的参数 socket 代表的是当前的 client 和 server 间建立的这个连接。可在 client 程序中将这个建立的 socket  连接打印出来,如下图所示:

如何使用socket.io实现消息实时推送功能

其中的 id 属性可以用于标识出这一连接,从而 server 可以向特定的用户发送消息。

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 来向用户推送消息。

对用户信息的处理

方便起见,这里只用一个数组保存用户信息,实际工作中可以根据需要放入数据库中保存。

global.users = []; // 记录下登录用户的tokenId, socketId

当用户登录时,client 会向 server 发送 user_login 事件,服务器接收到后会做如下操作:

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

addSocketId() 会向 users 数组中添加用户信息,不同用户通过 tokenId 进行区分,每个用户有一个 socketIds  数组,保存可能存在的多个 socketId。该函数的具体代码可见 src/utils.js 文件。

同理,还有一个 deleteSocketId() 函数用于删除用户信息,代码可见同一文件。

在获取了用户的 tokenId 之后,就需要找到对应的 socketId,然后向特定用户推送消息。

// 只向 id = socketId 的这一连接发送消息  io.sockets.to(socketId).emit('receive_message', {     entityType,     data });

服务器的思路大致如此,接下来介绍客户端中是如何进行相应的处理的。

客户端

Socket.io 的初始化

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

其它的引入方式:

const io = require('socket.io-client');  // or with import syntax  import io from 'socket.io-client';

引入 Socket.io 后就获得了 io 函数,通过它来与消息推送服务器建立连接。

// 假设你将 Node 服务器部署后的地址为:https://www.example.com/ws // 则: WS_HOST = 'https://www.example.com' const msgSocket = io(`${WS_HOST}`, {     secure: true,     path: '/ws/socket.io' });

如果监听本地:

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

这里如果写成 io('https://www.example.com/ws') 会出现错误,需要将 /ws 写入path中。

为了能在其它文件使用这一变量,可将 msgSocket 作为一个全局变量:

window.msgSocket = msgSocket;

用户建立连接

// 用户登录时,向服务器发送用户的信息。服务器会在收到信息后建立 socket 与用户的映射。 msgSocket.emit('user_login', {     userId,     socketId: msgSocket.id,     tokenId });

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

// WebSocket 连接建立后,监听名为 receive_message 的事件  msgSocket.on('receive_message', msg => {     store.dispatch({         type: 'NEW_SOCKET_MSG',         payload: msg     }); });

当 WebSocket 服务器向客户端推送了消息之后,客户端需要监听 receive_message 事件,接收到的参数中有相应待处理的信息。

由于使用了 Redux 进行数据的处理,所以这里 dispatch 了一个 NEW_SOCKET_MSG action,后续则是常规的 redux  处理流程了。

项目的使用

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

npm run dev

即可在 devlopment 环境下进行测试,现在你就有了一个运行在4001端口的消息推送服务器了。

但是这里并没有后端的服务器来向我们发送消息,所以我们将利用 Postman 来模拟发送消息。

为了展示程序的功能,在项目的 client 文件夹下放置了一个 index.html  文件。注意这个文件并不能用在实际的项目中,只是用来显示消息推送的效果而已。

在开启了服务器之后,打开 client/index.html,根据提示随意输入一个 tokenId 即可。

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

{      // tokens 数组表示你想向哪个用户推送消息     "tokens": ["1", "2"],      "data": "You shall not pass!!!" }

如何使用socket.io实现消息实时推送功能

至此,如果一切顺利,你应该能够在 client 的控制台中看到收到的消息了。

如何使用socket.io实现消息实时推送功能

以上就是如何使用socket.io实现消息实时推送功能,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注编程笔记行业资讯频道。


推荐阅读
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 本文详细解析了muduo库中的Socket封装及字节序转换功能。主要涉及`Endian.h`和`SocketsOps.h`两个头文件,以及`Socket.h`和`InetAddress.h`类的实现。 ... [详细]
  • 本文介绍了一个基本的同步Socket程序,演示了如何实现客户端与服务器之间的简单消息传递。此外,文章还概述了Socket的基本工作流程,并计划在未来探讨同步与异步Socket的区别。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 深入理解Java泛型:JDK 5的新特性
    本文详细介绍了Java泛型的概念及其在JDK 5中的应用,通过具体代码示例解释了泛型的引入、作用和优势。同时,探讨了泛型类、泛型方法和泛型接口的实现,并深入讲解了通配符的使用。 ... [详细]
  • 本文详细探讨了如何在Docker环境中实现单机部署Redis集群的方法,提供了详细的步骤和配置示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文介绍如何使用 Android 的 Canvas 和 View 组件创建一个简单的绘图板应用程序,支持触摸绘画和保存图片功能。 ... [详细]
  • 在尝试使用C# Windows Forms客户端通过SignalR连接到ASP.NET服务器时,遇到了内部服务器错误(500)。本文将详细探讨问题的原因及解决方案。 ... [详细]
  • Linux环境下通过PHP SMTP发送邮件的配置指南
    本文详细介绍了如何在Linux系统中配置PHP通过SMTP发送邮件,包括防火墙设置、端口检查与释放、IPv6到IPv4的转换、DNS缓存刷新以及PHP相关配置等步骤。 ... [详细]
  • 中科院学位论文排版指南
    随着毕业季的到来,许多即将毕业的学生开始撰写学位论文。本文介绍了使用LaTeX排版学位论文的方法,特别是针对中国科学院大学研究生学位论文撰写规范指导意见的最新要求。LaTeX以其精确的控制和美观的排版效果成为许多学者的首选。 ... [详细]
author-avatar
无情的有情人家_834
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有