likes
comments
collection
share

EventSource VS WebSocket

作者站长头像
站长
· 阅读数 15

EventSource

定义

EventSource也称为SSE(Server-Sent Events),是服务器推送的一个网络事件接口,一个EventSource会对http服务开启一个持久化链接,它发送的事件格式是‘text/stream’,开启EventSource事件后,它会一直保持开启状态,直到被要求关闭

Server使用

我采用的是node + Koa的方式,由于它是属于http的请求方式,所以通过路由匹配,主要需要设置{'Content-Type': 'text/event-stream'}形式

 const app = new Koa();
 app.use(async (ctx, next) => {
    if (ctx.path === '/stream') {
        ctx.request.socket.setTimeout(0)
        ctx.req.socket.setNoDelay(true)
        ctx.req.socket.setKeepAlive(true)
        ctx.set({
            'Content-Type': 'text/event-stream',
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive',
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Credentials': 'true'
        })
        const stream = new PassThrough()
        ctx.status = 200
        ctx.body = stream
        setInterval(() => {
            stream.write(`data: ${new Date()}\n\n`)
        }, 1000)
        return
    }

    try {
        await next()
    } 
})

client使用

初始化事件对象, EventSource第一个参数是访问的http的url, 第二个config主要配置跨域属性, 3000是客户端端口,通过proxy代理到后端

let serverEvent = new EventSource('http://localhost:3000/stream', {
  withCredentials: true
})

EventSource VS WebSocket

相关的事件监听方法

serverEvent.onopen = (event) => {
  console.log(event, 'onopen----event00000')
}
// 连接成功,消息推送
serverEvent.onmessage = (event) => {
  console.log(event, 'onmessage----event00000')
}

// 服务发生异常,譬如跨域问题等
serverEvent.onerror = (event) => {
  console.log(event, 'onerror----event00000')
}

由于它在http下,所以你在network中可以找到对应的api,在里面有EventStream就是对应的返回结果,如果报错可以通过查看返回的status等信息排查问题原因

EventSource VS WebSocket

WebSocket

定义

WebSocket可以在用户的浏览器和服务器之间打开交互的通信方式,使用此API,您可以向服务器发送消息并接受事件驱动的响应,而无需通过轮训服务器的方式获得相应。

server使用

在server端,新建目录文件wss/websocket.js, 其内容如下, 其中WebSocket.Server的第一个参数是后端开启的server服务,path对应的是websocket的路径,不填写默认是'/',我这里采用的ws的库,另外还有像socket.io等库

const WebSocket = require('ws')
class ws {
  static ws = WebSocket.Server // 默认实例
  static init (server) {
      // 创建实例
      // eslint-disable-next-line new-cap
      console.log('this.init, this.init, this.init, ')
      this.ws = new WebSocket.Server({ server, path: '/websocket' })
      this.ws.on('connection', async (ws, request) => {
          let count = 0
          this.ws.clients.forEach(client => {
              setInterval(() => {
                  const data = {
                      id: count,
                      firstName: `first-${count}`
                  }
                  client.send(JSON.stringify(data))
                  count++
              }, 2000)
          })
          this.ws.send('connected')
      })
  }
}

module.exports = ws

client使用

这里WebSocket后面添加的是ws对应的url,其中3000是客户端端口,websocket对应的路径同server端WebSocket.Server第二个参数path对应。

const exampleSocket = new WebSocket(
  "ws://localhost:3000/websocket"
);

exampleSocket.onmessage = (event) => {
  const data = JSON.parse(event.data)
  if (data?.id >= 3) {
    exampleSocket.close();
  }
}

需要注意的是,这里如果需要访问proxy到服务端,通过vite/webpack相关配置里需要加{ws: true}的属性,如下图所示

EventSource VS WebSocket 另外,它的数据查看方式是在network下的ws中查看

EventSource VS WebSocket

对比

EventSourceWebSocket
单向传输(server 到 client)双向传输
基于http协议基于tcp协议
只支持文本(utf-8)支持二进制/文本(utf-8)格式数据传输
浏览器限制传输个数(chrome 限制6个,因为是http请求,http1.0有限制)浏览器不限制
轻量级协议,实现简单重量级协议,实现复杂
支持断开重连需要额外部署
不支持跨域,需要设置header支持跨域
没有防火墙阻塞有防火墙