服务器与客户端的实时通信

服务器与客户端的实时通信

我们在做聊天室的时候,会需要用到实时通信,当服务端向客户端提前声明,发送的是流信息的时候,HTTP 协议可以允许服务器向客户端发送消息,因为一次性发送不完,需要连续不断的发送,客户端不会关闭连接,会一直等着服务器发送新的数据流。

服务端与客户端的实时通信,主要有以下三种解决方案:

轮询

前端可以在自己的页面进行轮询(定时)调用后端的接口,然后触发后端给前端返回消息,虽然可以解决前后端实时推送的数据问题,但是这样做并不是一个最优解,使用 WebSocket 和 SSE 更好一点。

WebSocket

WebSocket 是一个全双工通道,客户端可以给服务端发送消息,并且可以接收服务端的消息,服务端也可以给客户端发送消息,接收客户端的消息。

websocket 有很多特点:

  1. 建立在 TCP 协议之上,服务器端的实现比较容易
  2. 与 HTTP 协议有着良好的兼容性。默认端口也是 80 和 443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
  3. 数据格式比较轻量,性能开销小,通信高效。
  4. 可以发送文本,也可以发送二进制数据。
  5. 没有同源限制,客户端可以与任意服务器通信。
  6. 协议标识符是 ws(如果加密,则为 wss),服务器网址就是 URL。

像直播的聊天室都是 WebSocket 做的。我们在使用 WebSocket 的时候,可以使用 socket.io 这个库,会方便很多。在前端页面需要依靠 socket.io.js,node 要依靠socket.io的库。

用一个简单的 socket.io 的例子,实现一下精简版的互相通信。废话不多说,上代码:

server 端:

const Koa = require('koa');
const app = new Koa();
const server = require('http').Server(app.callback());
const io = require('socket.io')(server);
const port = 8081;

server.listen(process.env.PORT || port, () => {
  console.log(`app run at : http://127.0.0.1:${port}`);
});

io.on('connection', socket => {
  console.log('初始化成功!下面可以用socket绑定事件和触发事件了');
  socket.on('send', data => {
    console.log('客户端发送的内容:', data);
    socket.emit('getMsg', '我是返回的消息... ...');
  });

  setInterval(() => {
    socket.emit('getMsg', '我是初始化3s后的返回消息... ...');
  }, 3000);
});
复制代码

client 端:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>websocket示例</title>
  </head>
  <body>
    <button id="send">发送消息到服务器</button>
    <div>
      <h3>服务器响应的消息:</h3>
      <i id="msg"></i>
    </div>

    <script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
    <script>
      var socket = io('ws://localhost:8081');
      var send = document.querySelector('#send');
      var msg = document.querySelector('#msg');

      socket.on('getMsg', data => {
        console.log('服务端消息:', data);
        msg.innerHTML += `${data} <br/>`;
      });

      socket.on('message', data => {
        console.log('服务端消息:', data);
        // msg.innerHTML += `${data} <br/>`;
      });

      send.onclick = () => {
        console.log('点击了发送消息!');
        socket.emit('send', 'hello');
      };
    </script>
  </body>
</html>
复制代码
  • 前端通过 socket.on('事件名', callback)监听到后端的触发
  • 前端通过 socket.emit('事件名', '消息体')向后端发送消息
  • 后端通过 socket.emit('事件名', '消息体')向前端发送消息
  • 后端通过 socket.on('事件名', callback)接收前端发送来的消息
  • 后端通过 socket.on('disconnect')监听退出事件
  • 后端可以通过 socket.broadcast.emit('message', '消息内容')进行广播

SSE(Server-Sent Events)

SSE 相对于 WebSocket 来说,没有 WebSocket 那么强大,因为 WebSocket 是全双工通道,但是 SSE 是单向通道,只能服务器向浏览器发送信息。

但是 SSE 相对 WebSocket 来说,也有自己的优点:

  1. 轻量级,使用简单,没有 WebSocket 的协议那么复杂
  2. 默认断线重连,WebSocket 需要自己去实现
  3. SSE 一般用来发送文本,如果发送二进制数据,需要编码后传输,WebSocket 默认支持传送二进制数据

具体的代码示例可以参考 javascript.ruanyifeng.com/htmlapi/eve…

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值