EventSource实现服务端与客户端通信案例实战

项目需求:数据展示实时更新
解决方案:在第一时间想到的是通过前端轮询的方式请求后端接口,达到数据更新的目的,但是存在以下缺点

  1. 数据不能做到实施更新,有一定时间的延迟
  2. 消耗大量的系统资源

优化方案:使用EventSource的方式来实现该需求,能够解决以上问题


目录

1. EventSource基本介绍

2. EventSource特性

3. EventSource工作原理

4. EventSource常用方法

5. 实战案例:Vue+SpringBoot


1. EventSource基本介绍

        EventSource是一种用于实现服务器推送事件的Web API,它允许服务器向客户端发送数据流,而无需客户端发出请求。EventSource架构的设计思想是建立一种持久连接,通过这个连接发送事件流,以实现通信。

        文档地址

2. EventSource特性

  1. 实时性。EventSource能够实现实时地数据传输,可以在服务器端有新事件时立即向客户端推送,并自动进行展示。
  2. 低延迟。由于EventSource采用长连接的方式进行传输,相比于普通的轮询方式,它能够更加高效地传输数据。
  3. 易用性。EventSource是一种非常易用的API,只需要在客户端创建一个EventSource对象,指定服务器端的URL,即可进行监听并展示事件。
  4. 兼容性。EventSource能够同时兼容WebSocket和长轮询等方式,具备很好的兼容性,可以在各种不同的场景下使用。

3. EventSource工作原理

        EventSource的原理基于Http协议,它允许服务器与客户端建立持久的连接,以便服务器能够向客户端推送事件数据。以下是EventSource的工作原理客户端发起请求:客户端通过创建一个EventSource对象,并向服务器发起一个HTTP GET请求,请求一个特定的URL。

  1. 服务器响应:服务器接收客户端的请求,并在HTTP头中添加Content-Type: text/event-stream,表明将发送的事件数据格式为text/event-stream。

  2. 建立持久连接:服务器与客户端建立一个持续的HTTP连接,并开始向客户端发送数据,直到连接被关闭。

  3. 发送事件数据:当服务器有新的事件数据要发送时,它将按照特定格式发送给客户端。事件数据通常以event:eventName;data:eventData;的形式发送,其中event字段表示事件名,data字段表示事件数据。

  4. 客户端接收数据:客户端通过EventSource对象注册事件处理函数,以接收来自服务器的事件数据。当接收到事件数据时,客户端会创建一个Event对象,并触发相应的事件处理函数,传递Event对象作为参数。Event对象包含type(事件类型,通常为"message")、data(事件数据)、lastEventId(上一个事件的ID)、origin(事件源的URL)等属性。

  5. 错误处理和重连:如果连接出现错误或被关闭,客户端将触发“error”事件或“close”事件,以便进行错误处理或重新连接。

  6. 单向通信:EventSource支持单向通信,即只能从服务器向客户端推送数据,不支持客户端向服务器发送数据。这种特性使它适用于需要实时更新的应用程序场景,如聊天室、股票市场等。

  7. 自动重连接:EventSource支持自动重连接功能,如果连接中断,它可以尝试自动恢复连接。

  8. 发送随机事件:EventSource允许服务器发送没有明确事件名的随机事件,这种情况下,如果没有指定事件名的匹配事件处理函数,则会触发通用事件处理函数。

        总的来说,EventSource提供了一种简单的方式来实现服务器向客户端的实时数据推送,特别适合于不需要双向通信的场景。

4. EventSource常用方法

        1. 创建EventSource对象,其中url是服务器端推送数据的地址。

var evtSource = new EventSource(url);

        2.  onopen:连接建立时触发

evtSource.onopen = function () {
  console.log("Connection to server opened.");
};

        3. onmessage:接收到服务器端发送的数据时触发。

evtSource.onmessage = (e) => {
  console.log(e.data)
};

        4. onerror:连接出错时触发。

evtSource.onerror = function () {
  console.log("连接失败");
};

5. 实战案例:Vue+SpringBoot

前端代码:

        methods: {
                handleEventSoure() {
                    const eventSource = new EventSource('/source/test') // 连接地址

                    eventSource.onopen = () => { // 开始连接
                        console.log("连接成功")
                    }

                    eventSource.onmessage = (event) => { // 接收消息
                        console.log(event.data)
                    }

                    eventSource.onerror = () => { // 连接失败
                        console.log("连接失败")
                    }
                },
           },
        mounted() {
            this.handleEventSoure()
        }

后端代码:

@RestController
@RequestMapping("/source")
public class SysLoginInfoController extends BaseController {

    @GetMapping("/test")
    public Flux<String> test(HttpServletResponse response, HttpServletRequest req) {
        
        //设置响应的内容类型为HTML,字符集为UTF-8。
        response.setContentType("text/html;charset=utf-8");
        // 设置响应头,指明这是一个EventSource响应
        response.setHeader("Content-Type", "text/event-stream");
        //设置响应头"Cache-Control"为"no-cache",表示不允许缓存此响应。
        response.setHeader("Cache-Control", "no-cache");
        //设置响应头"Connection"为"keep-alive",表示保持连接。
        response.setHeader("Connection", "keep-alive");


        //返回的是一个字符串流 返回数据:好的 + 当前时间
        return Flux.interval(Duration.ofSeconds(1)).map(sequence -> "data: 好的" + new Date() + "");

    }

}

效果展示:

至此大功告成

年少鸡鸣方就枕,老人枕上待鸡鸣。转头三十余年梦,不道消磨只数声。

  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Python中实现WebSocket服务端客户端,可以使用Python websockets库。该库基于asyncio异步IO构建,提供了基于协程的API。 首先,你需要安装websockets库,可以使用pip命令进行安装:pip3 install websockets。 对于服务端实现,你可以创建一个Python文件,并引入websockets和asyncio模块。使用async关键字定义一个async函数,例如叫做handle_client,这个函数将处理客户端连接并处理接收到的消息。在函数内部,使用async with语句创建一个WebSocket服务器对象,传入服务器的地址和端口。然后,使用一个无限循环来等待并处理客户端连接。在循环中,使用await关键字接收客户端发送的消息,并根据需要进行处理。最后,使用await关键字向客户端发送消息。下面是一个简单的示例代码: ```python import asyncio import websockets async def handle_client(websocket, path): async for message in websocket: # 处理接收到的消息 # ... # 发送消息给客户端 response = "Hello, client!" await websocket.send(response) start_server = websockets.serve(handle_client, 'localhost', 8765) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever() ``` 对于客户端实现,你可以创建一个Python文件,并引入websockets和asyncio模块。使用async关键字定义一个async函数,例如叫做connect_to_server,这个函数将连接到服务器并发送消息。在函数内部,使用async with语句创建一个WebSocket客户端对象,传入服务器的地址和端口。然后,使用await关键字向服务器发送消息,并等待服务器的响应。最后,打印接收到的消息。下面是一个简单的示例代码: ```python import asyncio import websockets async def connect_to_server(): async with websockets.connect('ws://localhost:8765') as websocket: message = "Hello, server!" await websocket.send(message) response = await websocket.recv() print(response) asyncio.get_event_loop().run_until_complete(connect_to_server()) ``` 需要注意的是,以上示例只是一个简单的示例,你可以根据自己的需求进行修改和扩展。另外,确保你的Python版本是大于等于3.6的版本,因为websockets库对于较低版本的Python可能会有兼容性问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值