后端koa2前端ReactHooks中完成socket长连接(附源码)

后端koa2前端ReactHooks中完成socket长连接(附源码)

webSocket TCP长连接在平时中常用于一些高频前后端交互的场景,比如在线聊天、在线协作等;在以前时,一些项目中的通知与公告功能常用轮询来完成类webSocket的操作,但是这种方法频繁三次握手访问后端服务器,对服务器造成不小的压力,所以用webSocke长连接取代轮询是很有必要的;本次我就个人的开源项目里面的通知与公告功能来做案例,文章手把手帮您完成项目的socket的配置;项目源码在我个人的开源项目中,如果觉得可以,欢迎给作者收藏点赞~ 🥗

个人开源项目地址

一、了解socket.IO

一开始我个人是想选择koa-websocket的,但是实际使用后,发现这个文档不全、生态不够丰富,并且和我的项目并不是很契合,最终放弃了它,选择了socket.IOsocket.IO不仅官网文档很全,案例丰富,而且还特别契合我现在的项目,所以最终选择了它,实际使用感受确实好用;socket.IO是一个建立在webSocket协议上的库,它在服务器和客户端之间提供双向和低延迟的通信通道;

Socket.IO官方文档

二、koa2服务端使用socket.IO

2-1、安装

lua 复制代码
npm install socket.io

2-2、创建实例,并绑定到HTTP服务器

appuse注册页面,导入socket.iocreateServer创建实例绑定到HTTP服务器上,共用一个ip端口;cros解决跨域问题,io.of()配置独立的命名空间,.on监听连接事件,wsNotice是我个人封装的处理事件的函数;

ts 复制代码
import { Server } from 'socket.io' 

// ...中间一系列app.use注册,详细代码可下载源码查看

// 创建 Socket.IO 实例并绑定到 HTTP 服务器
const httpServer = createServer(app.callback())
const io = new Server(httpServer, {
  cors: {
    origin: '*',
    methods: ['GET', 'POST']
  }
})

// 在koa2应用中定义各种Socket.IO事件监听和处理
io.of('/wsNotice').on('connection', (socke封装t) => wsNotice(socket))

2-3、封装处理事件函数wsNotice

ts 复制代码
import SysNotice from '@/mysql/model/system/notice.model'
import { Socket } from 'socket.io'
import { DefaultEventsMap } from 'socket.io/dist/typed-events'
import { formatHumpLineTransfer } from '.'
import { queryConditionsData } from '../service'
import jwt from 'jsonwebtoken'
import env from '@/config/default'
import { IuserTokenType } from '@/types/auth'
import { judgeKeyOverdue } from './auth'

export const wsNotice = async (
  socket: Socket<DefaultEventsMap, DefaultEventsMap, DefaultEventsMap, any>
) => {
  const token = socket.handshake.query.token

  if (judgeToken(token as string)) {
    socket.on('postNotice', async (data) => {
      // 向所有的socket发送通知
      socket.broadcast.emit('getNotice', data)
      socket.emit('getNotice', data)

      // 向所有的socket更新通知公告
      socket.emit('getAllNotice', await getAllNoticeFn())
      socket.broadcast.emit('getAllNotice', await getAllNoticeFn())
    })

    socket.emit('getAllNotice', await getAllNoticeFn())

    socket.on('disconnect', (reason) => {
      console.log('socket已断开')
    })
  } else {
    socket.disconnect(true)
    console.error('token过期,断开socket连接')
  }
}

/**
 * 查询所有通知公告
 * @returns
 */
async function getAllNoticeFn() {
  return formatHumpLineTransfer(await queryConditionsData(SysNotice, { status: '0' }))
}

/**
 * 判断token是否有效
 * @param token
 * @returns
 */
async function judgeToken(token: string) {
  const user = jwt.verify(token, env().JWT_SECRET) as IuserTokenType
  return await judgeKeyOverdue(user.session)
}

其中向所有的socket连接发送消息,也可以选择使用socket.IO中的广播事件和房间,因为这里的需求很简单,所以就用最基本的操作了,可以按照自己的实际需求更改的哈~

三、ReactHooks客户端端使用socket.IO

客户端安装 socket.io-client 这个包,然后配置通信地址即可;

3-1、安装

lua 复制代码
npm install socket.io-client

3-2、封装创建socket的函数

tsx 复制代码
import useStore from '@/store'
import { InoticeType } from '@/type/modules/system/notice'
import { notification } from 'antd'
import { io } from 'socket.io-client'

const createSocket = (pathName: string) => {
  const {
    useSocketStore: { setNotices },
    useUserStore: { token },
  } = useStore()
  
  // forceNew开启命名空间,query携带用户token
  const socket = io(`${process.env.BASE_ENV}/${pathName}`, { forceNew: true, query: { token }})

  socket.on('connect', () => {
    console.log('socket是否连接成功' + socket.connected) // true
  })
  socket.on('connect_error', (err) => {
    console.log('socket连接失败', err)
    setTimeout(() => {
      socket.connect()
    }, 5000)
  })

  // 获取所有公告和通知
  socket.on('getAllNotice', (data: InoticeType[]) => {
    setNotices(data)
  })
  // 获取单条公告和通知
  socket.on('getNotice', (data: InoticeType) => {
    notification.info({
      message: data.noticeTitle,
      description: <div dangerouslySetInnerHTML={{ __html: data.noticeContent as string }} />,
    })
  })

  socket.on('disconnect', (reason) => {
    // 服务器断开socket连接时
    if (reason === 'io server disconnect') {
      socket.connect()
    }
    console.log('socket已断开', reason)
  })

  return socket
}

export default createSocket

3-3、在layout初始化的时候连接socket(地方可自行选择)

scss 复制代码
  useEffect(() => {
    // 初始化连接socket
    const socket = createSocket('wsNotice')
    // 存储socket实例,在通知模块,立即通知处需要用到socket.emit事件立即向所有用户发送通知信息
    setSocket(socket)
  }, [])

结语

以上用socket.IO完成最基础的通知与公告功能,如果自己有更复杂的业务,可以自行官网研究~🌮

相关推荐
源码获取_wx:Fegn08952 分钟前
计算机毕业设计|基于springboot + vue鲜花销售管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
毕设源码-赖学姐17 分钟前
【开题答辩全过程】以 基于SpringBoot 的个人健康分析指导系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
源代码•宸20 分钟前
简版抖音项目——项目需求、项目整体设计、Gin 框架使用、视频模块方案设计、用户与鉴权模块方案设计、JWT
经验分享·后端·golang·音视频·gin·jwt·gorm
礼拜天没时间.1 小时前
Node.js运维部署实战:从0到1开始搭建Node.js运行环境
linux·运维·后端·centos·node.js·sre
Dragon Wu2 小时前
SpringCache 缓存使用总结
spring boot·后端·spring·缓存·springcloud
夜瞬2 小时前
【Flask 框架学习】01:编写第一个 Flask 应用
后端·python·学习·flask
JavaLearnerZGQ2 小时前
Spring Boot 流式响应接口核心组件解析
java·spring boot·后端
Loo国昌2 小时前
【AI应用开发实战】07_文档解析路由与质量评估:从传统PDF解析到Docling现代化方案
人工智能·后端·python·自然语言处理·pdf
Pr Young2 小时前
有限状态机
服务器·后端
凌云拓界2 小时前
TypeWell全攻略:AI健康教练+实时热力图开发实战 引言
前端·人工智能·后端·python·交互·pyqt·数据可视化