网络-SSE


文章目录

  • 前言
  • 一、SSE简介
    • 1、SSE特点
      • Polyfill
    • 2、SSE原理
    • 3、SSE技术实现:
    • 4、SSE应用场景:
    • 5、EventSource
  • 二、SSE使用
    • 1、前端
    • 2、后端
    • 3、完整代码
      • 前端
      • 后端
  • 总结


前言

本文主要记录SSE通讯的简介、使用、以及原理和一个ChatGPT返回数据的demo。


一、SSE简介

SSE(Server-Sent Events,服务器推送事件)是一种用于在浏览器和服务器之间实现实时、单向通信的Web技术。它允许服务器向客户端推送数据,而无需客户端发起请求。与传统的HTTP请求-响应模式不同,SSE建立了一种持久的连接,通过这个连接,服务器可以随时向客户端发送更新的数据。这种实时通信的方式非常适用于需要实时更新数据的应用,如聊天应用、股票行情、实时监控等。

1、SSE特点

  • 简单易用:SSE使用简单的API,只需要创建EventSource对象并监听事件即可实现实时通信。
  • 单向通信:SSE是一种单向通信方式,只允许服务器向客户端推送数据,而不支持客户端向服务器发送请求。
  • 实时性:SSE建立了持久连接,服务器可以随时向客户端发送更新的数据,实现实时的数据推送。
  • 自动重连:如果连接中断,SSE会自动尝试重新建立连接,确保持久连接的稳定性。
  • 支持事件流:SSE使用事件流(event stream)的格式来传输数据,可以发送不同类型的事件,方便客户端进行处理。

需要注意的是,SSE在一些旧版本的浏览器中可能不被完全支持。但是,大多数现代浏览器都支持SSE,并且可以通过Polyfill来提供兼容性支持。

Polyfill

Polyfill是一种用于填充浏览器或环境中缺少的功能或API的代码。它可以在旧版本的浏览器或不支持某些新特性的环境中,提供对这些功能的兼容性支持。当新的Web标准或API被引入时,不同的浏览器或环境可能会以不同的速度进行支持和实现。在这种情况下,开发人员可以使用Polyfill来填充这些缺失的功能。

Polyfill通常是一个JavaScript库或脚本,它通过在运行时检测浏览器或环境的功能支持情况,然后根据需要动态地添加缺失的功能或API的实现。例如,如果某个浏览器不支持ES6的新特性,如箭头函数、模板字符串等,开发人员可以使用相应的Polyfill来提供对这些特性的支持。Polyfill会检测浏览器是否支持这些特性,如果不支持,则在运行时添加相应的代码来实现这些特性。

需要注意的是,Polyfill并不是一种通用的解决方案,它可能会增加页面的加载时间和代码体积。因此,在使用Polyfill时,需要根据具体的需求和目标浏览器进行选择和优化。

2、SSE原理

  • 客户端通过创建一个EventSource对象来与服务器建立连接。
  • 服务器通过发送特定格式的事件流(event stream)数据,将数据推送给客户端。
  • 客户端通过监听EventSource对象的事件,如message事件,来接收服务器发送的数据。
  • 服务器可以根据需要发送不同类型的事件,如message事件、open事件、error事件等。

3、SSE技术实现:

SSE基于HTTP协议,利用其长连接特性,通过浏览器向服务器发送一个HTTP请求,建立一条持久化连接。

4、SSE应用场景:

  • 实时数据大屏(这种不需要客户端做操作的,只需要服务端将数据不断给客户端,并且需要长时间连接,并不一定需要WebSocket
  • chatGPT 返回数据

5、EventSource

EventSource是HTML5中的一个API,用于在客户端与服务器之间建立基于HTTP的单向通信。

二、SSE使用

1、前端

  • 创建EventSource对象:
    在客户端的JavaScript代码中,使用new EventSource(url,options)来创建一个EventSource对象.
    • 其中url是服务器端的URL,必填。
    • options是配置项可选参数Object类型,常用配置包括:
      • withCredentials:Boolean类型,标识是否允许发送CoolieHTTP认证信息。默认false
      • headers:Object类型,标识发送的请求头信息。
      • retryInterval:Number类型,标识与服务器失去连接后,重连时间间隔。默认1000毫秒
 const sse = new EventSource('http://localhost:3000/api/sse',{
                withCredentials:false,
                headers:{},
                retryInterval: 1000
            })
  • 监听事件:
    通过为EventSource对象添加事件监听器,如onmessage、onopen、onerror等,来处理服务器发送的事件。
    • onmessage:表示已经收到服务端数据。
    • onopen:表示已经建立了连接,并开始接收服务端数据。当后端没有定义返回的事件,默认是该事件。
    • onerror:表示建立连接或接收数据时发生错误。
  • 接收事件:
    当服务器发送事件流数据时,EventSource对象会触发相应的事件,客户端可以通过事件监听器来接收和处理这些事件。
 sse.onopen = (e) =>{
                console.log('连接成功', e)
            }
            sse.onmessage = (e) =>{
                console.log('接收到数据', e)
            }
            sse.onerror= (e) =>{
                console.log('发生错误',e)
            }
            sse.addEventListener('message',(e)=>{
                const span = document.getElementById('animate')
                span.remove()
                message.innerHTML += `${e.data}|`
            })
  • 关闭连接:
    如果不再需要与服务器保持连接,可以调用EventSource对象的close()方法来关闭连接。
stop.addEventListener('click',(e)=>{
                console.log('断开连接',e)
                sse.close()
            })

2、后端

后端必须设置响应头 'Content-Type': 'text/event-stream',然后其他就和普通get请求一样。

后端是可以设置事件名称的,返回event 表示定义事件名称

res.write(`event:dg\n`)

3、完整代码

前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    .box{
        height: 100vh;
        width: 100%;
        background: #1B1A22;
    }
    #message{
        color: white;
    }
    #animate{
        display: inline-block;
        padding:0 5px;
        font-size:20px;
        font-weight: bold;
        animation: fade 1s infinite forwards;
    }
    @keyframes fade {
        from{
            opacity: 0;
        }
        to {
            opacity: 1;
        }
    }
</style>
<body>
<div>
    <div class="box">
        <div id="message"><span id="animate">|</span></div>
        <div style="margin-top: 30px"><button id="stop">断开连接</button></div>
    </div>
</div>
</body>
<script>
    const message = document.getElementById('message')
    const stop = document.getElementById('stop')
    document.addEventListener('keydown',(e)=>{
        if (e.keyCode == 13){
            const sse = new EventSource('http://localhost:3000/api/sse',{
                withCredentials:false,
                headers:{},
                retryInterval: 1000
            })
            sse.onopen = (e) =>{
                console.log('连接成功', e)
            }
            sse.onmessage = (e) =>{
                console.log('接收到数据', e)
            }
            sse.onerror= (e) =>{
                console.log('发生错误',e)
            }
            sse.addEventListener('message',(e)=>{
                const span = document.getElementById('animate')
                span.remove()
                message.innerHTML += `${e.data}|`
            })
            stop.addEventListener('click',(e)=>{
                console.log('断开连接',e)
                sse.close()
            })

        }
    })

</script>
</html>

后端

这里后端用Node

app.get('/api/sse',(req,res)=>{
    res.writeHead(200,{
        'Content-Type': 'text/event-stream',
        'Access-Control-Allow-Origin': '*'
    })
    // 读取本地文件
    const txt =  fs.readFileSync('../SSE/index.txt','utf8')
    // 分割成字符数组
    const arr = txt.split('')
    let currnet = 0
    let timer = setInterval(()=>{
        if (currnet < arr.length){
            // 设置返回事件名称
            // res.write(`event:dg\n`)
            res.write(`data:${arr[currnet]}\n\n`)
            currnet++
        }else{
            clearTimeout(timer)
        }
    },300)

})

网络-SSE_第1张图片

注:
SSE是服务端主动向客户端发送数据,在客户端发送连接数据连接后,客户端就不能再向服务端发送数据了,只能服务端给客户端发送数据,这是因为SSE是单工通讯的。

只接受get请求

服务端没有设置正确的响应头信息,可能导致无法接收数据


总结

总的来说,SSE是一种简单、实时的通信技术,适用于需要实时推送数据的应用场景,提供了一种有效的方式来实现服务器向客户端的实时通信。

你可能感兴趣的:(网络,网络)