Eventsource vs Websocket vs Socket.io

JS实时通信eventsource, Eventsource、websocket与socket.io

在现代Web开发中,实时通信是一个非常重要的话题。当我们需要实现即时聊天、实时数据展示或实时游戏等功能时,选择合适的实时通信解决方案就显得格外重要。本文将介绍JS中三种常见的实时通信技术:eventsource、websocket和socket.io,并分析它们的特点和适用场景。

eventsource

一、eventsource是HTML5中新增的API,它提供了一种简单易用的方式来实现服务器向浏览器的即时推送。通过eventsource,我们可以建立一个持久连接,从而实现服务器端的事件推送到浏览器端。这使得我们能够轻松创建一个实时聊天室或实时数据展示页面。

eventsource具有超高效、最好用的特点。它使用简单,只需要通过JavaScript代码创建一个eventsource对象,并指定服务器端的URL。然后,我们可以监听事件,处理服务器端发送的消息。最重要的是,eventsource基于HTTP协议,所以可以兼容大部分浏览器。

优点:

  • 简单易用,与 HTTP 协议兼容。
  • 只需要一个长连接,服务器可以推送任意数量的事件。
  • 适用于服务端向客户端发送频率较低的数据。
  • 可以自动重连,并且在连接断开时会触发 error 和 close 事件,方便处理异常情况。

缺点:

  • 不支持双向通信。
  • 不支持二进制数据传输。
  • 兼容性存在问题,不支持 IE 浏览器。

示例:

const eventSource = new EventSource('/api/data');

eventSource.addEventListener('message', (event) => {
  console.log('Received message data:', event.data);
});

eventSource.addEventListener('error', (event) => {
  if (event.eventPhase === EventSource.CLOSED) {
    console.log('Connection was closed.');
  } else {
    console.error('An error occurred:', event);
  }
});

eventsource在实际项目中有许多应用场景。下面我列举几个常见的场景:

  1. 实时数据展示:eventsource可以用于实时展示服务器端的数据变化。比如,一个监控系统可以通过eventsource与服务器建立连接,服务器端监测到数据变化后,即时推送给客户端,客户端可以实时展示最新的数据。
  2. 实时聊天应用:eventsource可以用于实现实时聊天功能。当有新消息时,服务器可以使用eventsource向客户端推送消息,客户端即时收到消息并进行展示。这样就可以实现类似微信、QQ等实时聊天的功能。
  3. 实时通知提醒:eventsource可以用于发送实时通知提醒。比如,一个新闻网站可以使用eventsource向用户发送最新的新闻推送,用户无需手动刷新页面即可获取到最新的新闻内容。
  4. 实时博客评论:eventsource可以用于实时更新博客评论。当有新的评论提交时,服务器可以使用eventsource将新评论推送给其他正在浏览该博客的用户,实现实时更新评论的效果。
使用EventSource实现ChartGPT的打字效果输出示例:

在服务器端,创建一个能够生成GPT文本的函数或API。这个函数可以接收用户的输入,并根据输入生成相应的文本。

在前端页面中,使用JavaScript创建一个新的EventSource对象,指定服务器端的URL。例如:

var eventSource = new EventSource('/gpt');

在前端页面中,监听来自服务器端的message事件,该事件会在服务器端有新的数据发送时触发。在事件处理函数内部,将接收到的数据逐步添加到文本区域中,模拟打字效果。例如:

eventSource.addEventListener('message', function(event) {
  var textArea = document.getElementById('output');
  textArea.value += event.data; // 将接收到的数据逐步添加到文本区域中
});

在前端页面中,创建一个输入框或其他交互元素,用于用户输入。当用户输入完成后,将输入内容发送给服务器端。可以通过监听输入框的键盘事件或点击按钮等方式实现。例如:

var inputElement = document.getElementById('input');

inputElement.addEventListener('keyup', function(event) {
  if (event.key === 'Enter') {
    var userInput = inputElement.value;

    // 发送用户输入给服务器端
    var xhr = new XMLHttpRequest();
    xhr.open('POST', '/gpt');
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.send(JSON.stringify({ input: userInput }));

    inputElement.value = ''; // 清空输入框
  }
});

这样,当用户在前端页面中输入内容并发送给服务器端后,服务器端会生成相应的GPT文本,并使用EventSource将文本逐步发送给前端页面,实现打字效果的输出。

 

 

携带的数据是JSON格式的,浏览器都帮你整合成为一个Object:

综上所述,eventsource、websocket和socket.io都是常见的JS实时通信技术。根据具体需求和项目特点,我们可以选择合适的技术来实现实时通信功能。eventsource适用于简单的推送场景,websocket适用于双向通信场景,而socket.io则是一个更高级的实时通信库,提供了更多的功能和便利性。

无论你是要打造一个实时聊天应用、实时数据展示页面,还是开发实时游戏,选择合适的实时通信技术都是非常重要的。希望本文能够帮助你了解和选择合适的技术,使你的实时通信项目更加出彩!

websocket

二、websocket 与eventsource不同,websocket是一种全双工通信协议,它能够在浏览器和服务器之间建立双向通信的连接。相比于eventsource的单向通信,websocket可以同时实现浏览器向服务器的推送和服务器向浏览器的推送,实现真正的双向通信。

websocket具有极低的延迟,适用于实时游戏、聊天应用等场景。它使用ws或wss协议,能够在浏览器和服务器之间建立长时间的连接。通过websocket,我们可以发送和接收消息,实时更新数据,并处理各种事件。

优点:

  • 支持双向通信,客户端和服务端都可以发送和接收消息;
  • 可以发送二进制数据,支持大文件传输;
  • 协议比较轻量级,能够节省网络带宽和服务器资源;
  • 兼容性较好,大部分现代浏览器都支持 WebSocket。

缺点:

  • 需要在服务端实现 WebSocket 协议的支持;
  • 相对于 HTTP 请求来说,WebSocket 连接需要占用更多的服务端资源;
  • 安全性问题:需要注意防止 CSRF 和 XSS 攻击,避免恶意用户利用 WebSocket 劫持会话或注入脚本等。

示例:

const webSocket = new WebSocket('ws://localhost:8080');

webSocket.addEventListener('open', (event) => {
  console.log('WebSocket connection established!');
});

webSocket.addEventListener('message', (event) => {
  console.log('Received message data:', event.data);
});

webSocket.addEventListener('close', (event) => {
  console.log('WebSocket connection closed!');
});

webSocket.addEventListener('error', (event) => {
  console.error('An error occurred:', event);
});

// 发送消息到服务器
webSocket.send('Hello, server!');

socket.io

三、socket.io socket.io是一个基于websocket的实时通信库,它提供了更简单、更高级的API,使得实时通信变得更容易上手。socket.io能够自动选择最佳的通信方式,如果浏览器不支持websocket,它会自动降级为使用轮询方式进行通信。

socket.io不仅提供了基本的通信功能,还提供了一些小技巧来简化开发过程。例如,它支持房间(Room)概念,允许将多个用户分组在同一个房间中。这样,我们可以通过向特定房间发送消息来实现群聊等功能。

优点:

  • 支持双向通信。
  • 支持广播和房间功能,使得开发者可以轻松地实现实时应用程序。
  • 自带多种传输方式,如 WebSocket、HTTP 长轮询、JSONP 等,可以根据浏览器或设备的不同选择最佳传输方式。

缺点:

  • 使用 Socket.IO 的应用程序需要使用 Socket.IO 作为通信层,不能在应用程序中集成原生 WebSocket 或 EventSource
  • 对比 EventSource 和 WebSocket,Socket.IO 相对来说更加庞大,需要引入相应的客户端库和服务器端插件,如果应用程序只需要简单的实时通信,使用 EventSource 或 WebSocket 可能更加适合

示例:

// 客户端代码
const socket = io('http://localhost:3000');

socket.on('connect', () => {
  console.log('Socket.io connection established!');
});

socket.on('message', (data) => {
  console.log('Received message data:', data);
});

socket.on('disconnect', () => {
  console.log('Socket.io connection closed!');
});

socket.emit('message', 'Hello, server!');

// 服务端代码
const io = require('socket.io')(3000);

io.on('connection', (socket) => {
  console.log('A new client is connected!');

  socket.on('message', (data) => {
    console.log('Received message data:', data);
    socket.emit('message', `You said: ${data}`);
  });

  socket.on('disconnect', () => {
    console.log('Client disconnected!');
  });
});
<think>我们被要求使用Java中的WebSocketSseEmitter来实现实时流数据响应到页面的代码示例。根据引用[1][引用2],我们知道:-SseEmitter是Spring提供的用于服务器端推送事件(SSE)的工具,它允许服务器通过HTTP向客户端推送数据,是单向的(服务器到客户端)。-WebSocket则提供了全双工通信,适用于需要双向实时通信的场景。用户要求同时使用WebSocketSseEmitter,但请注意,这两种技术通常是独立使用的。不过,我们可以分别提供两种技术的代码示例,并说明它们的不同应用场景。由于问题中要求“通过WebSocketSseEmitter实现”,我们可以理解为分别展示两种方式。我们将分为两部分:1.使用SseEmitter实现SSE的示例2.使用WebSocket实现实时通信的示例注意:我们使用SpringBoot框架来简化开发。第一部分:使用SseEmitter实现SSE在Spring中,我们可以创建一个控制器来返回SseEmitter对象,然后在一个线程中定期发送数据。后端代码(Java):```javaimportorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;importorg.springframework.web.servlet.mvc.method.annotation.SseEmitter;@RestControllerpublicclassSseController{@GetMapping("/stream-sse")publicSseEmitterstreamSse(){SseEmitteremitter=newSseEmitter();//使用线程模拟数据推送newThread(()->{try{for(inti=0;i<10;i++){//发送数据,事件名为“message”(前端默认监听的事件)emitter.send(SseEmitter.event().name("message").data("SSEMessage"+i));Thread.sleep(1000);//模拟延迟}emitter.complete();//完成发送}catch(Exceptione){emitter.completeWithError(e);//出错}}).start();returnemitter;}}```前端代码(HTML/JavaScript):```html<!DOCTYPEhtml><html><head><title>SSEExample</title></head><body><divid="sse-output"></div><script>consteventSource=newEventSource('/stream-sse');eventSource.addEventListener('message',function(event){document.getElementById('sse-output').innerHTML+=event.data+'<br>';});</script></body></html>```第二部分:使用WebSocket实现在SpringBoot中,我们需要添加依赖(如spring-boot-starter-websocket)并配置WebSocket。1.添加依赖(pom.xml):```xml<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>```2.配置WebSocket(配置类):```javaimportorg.springframework.context.annotation.Configuration;importorg.springframework.web.socket.config.annotation.EnableWebSocket;importorg.springframework.web.socket.config.annotation.WebSocketConfigurer;importorg.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;@Configuration@EnableWebSocketpublicclassWebSocketConfigimplementsWebSocketConfigurer{@OverridepublicvoidregisterWebSocketHandlers(WebSocketHandlerRegistryregistry){registry.addHandler(newMyWebSocketHandler(),"/websocket");}}```3.创建WebSocket处理器:```javaimportorg.springframework.web.socket.TextMessage;importorg.springframework.web.socket.WebSocketSession;importorg.springframework.web.socket.handler.AbstractWebSocketHandler;importjava.io.IOException;importjava.util.concurrent.CopyOnWriteArrayList;publicclassMyWebSocketHandlerextendsAbstractWebSocketHandler{privatestaticfinalCopyOnWriteArrayList<WebSocketSession>sessions=newCopyOnWriteArrayList<>();@OverridepublicvoidafterConnectionEstablished(WebSocketSessionsession)throwsException{sessions.add(session);//模拟定时发送数据newThread(()->{for(inti=0;i<10;i++){try{Thread.sleep(1000);//向所有连接的会话发送消息for(WebSocketSessions:sessions){if(s.isOpen()){s.sendMessage(newTextMessage("WebSocketMessage"+i));}}}catch(Exceptione){e.printStackTrace();}}}).start();}}```4.前端代码(HTML/JavaScript):```html<!DOCTYPEhtml><html><head><title>WebSocketExample</title></head><body><divid="websocket-output"></div><script>constsocket=newWebSocket('ws://'+window.location.host+'/websocket');socket.onmessage=function(event){document.getElementById('websocket-output').innerHTML+=event.data+'<br>';};</script></body></html>```总结:-SSE(SseEmitter)适用于服务器向客户端推送数据的场景,实现简单,基于HTTP协议。-WebSocket适用于需要双向通信的场景,它建立在独立的TCP连接上。根据引用[2]中的比较,我们可以根据实际需求选择合适的技术。注意:在实际生产环境中,我们可能需要考虑连接管理、错误处理、安全性等问题,以上示例仅作为基础演示。§§相关问题§§1.在SpringBoot中如何配置SseEmitter的超时时间?2.WebSocketSSE在性能上有什么区别?3.如何确保WebSocket连接的安全性(比如使用wss)?4.在分布式环境下,如何扩展SSE或WebSocket应用?</think>以下是使用Java WebSocketSseEmitter实现实时流数据响应的代码示例及说明: ### 一、SSE方案(SseEmitter) 适合服务器向客户端单向推送数据的场景(如实时通知、日志流) #### 后端控制器(Spring Boot) ```java import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; @RestController public class SseController { @GetMapping("/stream") public SseEmitter streamData() { SseEmitter emitter = new SseEmitter(30_000L); // 超时时间30秒 // 模拟实时数据流(实际可替换为数据库监听/Kafka等) new Thread(() -> { try { for (int i = 1; i <= 10; i++) { // 发送格式:事件名 + JSON数据 emitter.send(SseEmitter.event() .name("sensorData") // 事件类型 .data("{\"value\":" + (i * 10) + ",\"timestamp\":" + System.currentTimeMillis() + "}")); Thread.sleep(1000); // 每秒发送 } emitter.complete(); // 正常结束 } catch (Exception e) { emitter.completeWithError(e); // 错误处理 } }).start(); return emitter; } } ``` #### 前端实现 ```html <div id="sse-output"></div> <script> const eventSource = new EventSource('/stream'); // 监听指定事件类型 eventSource.addEventListener('sensorData', (event) => { const data = JSON.parse(event.data); document.getElementById('sse-output').innerHTML += `实时值: ${data.value} | 时间: ${new Date(data.timestamp).toLocaleTimeString()}<br>`; }); // 错误处理 eventSource.onerror = (e) => { console.error("SSE连接错误:", e); eventSource.close(); }; </script> ``` --- ### 二、WebSocket方案 适合双向实时通信场景(如聊天室、协作编辑) #### 后端配置(Spring Boot) ```java import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; public class WebSocketHandler extends TextWebSocketHandler { private static final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) { sessions.add(session); // 启动数据推送线程 new Thread(() -> pushData(session)).start(); } private void pushData(WebSocketSession session) { try { for (int i = 0; i < 10; i++) { String payload = "WebSocket数据包-" + i; session.sendMessage(new TextMessage(payload)); Thread.sleep(1500); } } catch (Exception e) { // 异常处理 } } } ``` #### 前端实现 ```html <div id="ws-output"></div> <script> const socket = new WebSocket('ws://' + window.location.host + '/websocket-endpoint'); socket.onmessage = (event) => { document.getElementById('ws-output').innerHTML += event.data + '<br>'; }; socket.onclose = () => { console.log("WebSocket连接关闭"); }; </script> ``` --- ### 三、方案对比 | 特性 | SSE (SseEmitter) | WebSocket | |---------------|---------------------------|-------------------| | **通信方向** | 单向 (服务器→客户端) | 双向 | | **协议** | HTTP | 独立TCP协议 | | **断线重连** | 自动 | 需手动实现 | | **数据格式** | 文本/事件流 | 二进制/文本 | | **适用场景** | 实时通知、日志流 | 聊天室、游戏 | > 参考选择建议: > 1. 只需服务器推送:**SSE**(实现更简单,兼容HTTP生态)[^1] > 2. 需要双向交互:**WebSocket**(如实时编辑/游戏场景)[^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chengbo_eva

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值