WebSocket & socket.io
[[toc]]
前言
大家参与的项目里多少都会有web server与browser需要长连接互联的场景,
比如即时通讯、即时报价等,为了解决这个问题,便出现了 WebSocket 协议,实现了客户端和服务端双向通信的能力。
介绍 WebSocket 之前,还是让我们先了解下轮询实现推送的方式。
短轮询(Polling)
短轮询的实现思路就是浏览器端每隔几秒钟向服务器端发送 HTTP 请求,服务端在收到请求后,
不论是否有数据更新,都直接进行响应。在服务端响应完成,就会关闭这个 TCP 连接,
代码实现也最简单,就是利用 XHR , 通过 setInterval 定时向后端发送请求,以获取最新的数据
setInterval(function() { |
- 优点:实现简单。
- 缺点:会造成数据在一小段时间内不同步和大量无效的请求,安全性差、浪费资源。
长轮询(Long-Polling)
当服务器收到客户端发来的请求后,服务器端不会直接进行响应,而是先将这个请求挂起,
然后判断服务器端数据是否有更新。如果有更新,则进行响应,如果一直没有数据,则到达一定的时间限制(服务器端设置)才返回。
客户端JavaScript响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。
function queryData(){ |
- 优点:比 Polling 做了优化,有较好的时效性。
- 缺点:保持连接挂起会消耗资源,服务器没有返回有效数据,程序超时。
轮询与长轮询都是基于HTTP的,两者本身存在着缺陷:轮询需要更快的处理速度;长轮询则更要求处理并发的能力
;
两者都是“被动型服务器”的体现:服务器不会主动推送信息,而是在客户端发送ajax请求后进行返回的响应。
而理想的模型是”在服务器端数据有了变化后,可以主动推送给客户端”,这种”主动型”服务器是解决这类问题的很好的方案。Web Sockets就是这样的方案。
WebSocket
WebSocket是Html5定义的一个新协议,与传统的http协议不同,该协议可以实现服务器与客户端之间全双工通信。简单来说,首先需要在客户端和服务器端建立起一个连接,这部分需要http。
连接一旦建立,客户端和服务器端就处于平等的地位,可以相互发送数据,不存在请求和响应的区别。
当客户端要和服务端建立 WebSocket 连接时,在客户端和服务器的握手过程中,客户端首先会向服务端发送一个 HTTP 请求,
包含一个Upgrade 请求头 来告知服务端客户端想要建立一个 WebSocket 连接。
Connection: Upgrade |
WebSocket的优点是实现了双向通信,缺点是服务器端的逻辑非常复杂。现在针对不同的后台语言有不同的插件可以使用。
import React,{useEffect} from "react"; |
心跳检测
在实际使用 WebSocket 中,长时间不通消息可能会出现一些连接不稳定的情况,这些未知情况导致的连接中断会影响客户端与服务端之前的通信,
为了防止这种的情况的出现,有一种心跳保活的方法:客户端就像心跳一样每隔固定的时间发送一次 ping ,
来告诉服务器,我还活着,而服务器也会返回 pong ,来告诉客户端,服务器还活着。ping/pong,
其实是一条与业务无关的假消息,也称为心跳包。
可以在连接成功之后,每隔一个固定时间发送心跳包,比如 60s:
setInterval(() => { |
其中绿色
箭头表示发出
的消息,红色
箭头表示收到
的消息。
Socket.IO
- 可靠性,Socker.IO基于engine.io实现,先建立长轮询连接后再升级为基于websocket全双工的长连接
- 自动重连与断连检查
- 多路传输/多种数据格式传输(这个和websocket特性一样)
- 广播机制(这个用法在开发上还是很方便的,开发同学不需要做太多额外的工作,broadcast函数即可,不用像自己实现websocket服务端一样要做topic和连接管理及并发推送的处理)
Socket.io允许你触发或响应自定义的事件,除了connect,message,disconnect这些事件的名字不能使用之外,你可以触发任何自定义
的事件名称。
建立连接
const query = { |
消息收发
//发送数据 |
断开连接
//断开 |
适用场景
只从两个方面分析:
易用性: Socket.IO的易用性更好,对于前端开发来说,没有太多心智负担,比如需要关心重连、push转polling等容错逻辑; 服务端上也没有太多的连接管理的设计,Socker.IO已经打包处理了。
灵活性: 个人觉得websocket的灵活性更高一些,不管是前端还是后端,可以做更多的设计与优化,比如连接管理,容错重连,用户认证等,至少在提升技术能力上还是很有帮助。
SSE
Server-Sent Events 服务器推送事件跟长连接有啥区别 举个例子
Server-Sent Events (SSE) 是一种服务器推送技术,使客户端可以通过 HTTP 连接从服务器自动接收更新。与长轮询机制类似,区别是每个连接不只发送一个消息。客户端发送一个请求,服务端保持这个连接直到有新消息发送回客户端,仍然保持着连接,这样连接就可以消息的再次发送,由服务器单向发送给客户端³。
举个例子,假设现在需要经常获取后端的通知(比如新闻推送,消息推送),如果用长轮询实现只能用轮询做法,即每隔一段时间发起一次请求。这种方案的缺点非常明显:大量无用的请求;设定轮询间隔是件挺尴尬的事情——太短导致更多无用请求,浪费资源;太长导致无法及时收到后端的通知。而使用 SSE 的话,客户端向后端发起一个请求,建立起长连接(keep-alive connection)之后,后端可以随时往客户端推送数据了²。这样就避免了大量无用的请求和设定轮询间隔的问题。
属于长连接的一种 是单向通信的
跟 WebSockets 区别
WebSockets 也可以实现服务器向客户端推送数据。WebSockets 是一种双向通信协议,它允许客户端和服务器之间进行全双工通信。这意味着客户端和服务器都可以在任何时候发送数据。
与 Server-Sent Events 不同,WebSockets 不仅允许服务器向客户端发送数据,还允许客户端向服务器发送数据。这对于需要实时双向通信的应用程序非常有用,例如聊天应用程序或多人游戏。
tcp 跟 http 区别是什么
HTTP 和 TCP 都是计算机协议,它们都参与数据传输,但它们各自有其独特的用途,并且彼此相关。
HTTP(超文本传输协议)是一种请求-响应协议,允许用户在万维网(WWW)上通信数据并传输超文本。该协议仍然是使用互联网的主要方式之一,并为用户提供了一种通过传输超文本消息在客户端(例如 Chrome 等 Web 浏览器)和服务器之间交互 Web 资源(如 HTML 文件)的方式。它定义了 Web 浏览器和 Web 服务器之间通信的消息格式,也定义了 Web 浏览器应如何响应特定的 Web 请求。它是一种无状态协议,这意味着接收方不会保留先前请求的会话信息。
TCP(传输控制协议)是一种通信标准,使应用程序和计算设备能够在网络上交换数据和/或消息。它包含在 Internet 工程任务组(IETF)定义的标准中,并且是一种有状态协议。该协议定义了如何建立和维护网络连接,然后通过该连接交换数据。它还确定了如何将应用数据分解成网络可以传输的数据包,并确保端到端数据传输。
总之,HTTP 和 TCP 的主要区别在于:
- HTTP 通常使用端口 80,这是服务器“监听”或期望从 Web 客户端接收的端口¹。
- HTTP 比 TCP 快,因为它以更高的速度运行并立即执行过程¹。
- HTTP 是无状态协议,而 TCP 是有状态协议¹²³。
举个例子说明下
举个例子,假设你正在浏览网页,你的浏览器(客户端)会通过 HTTP 协议向服务器发送请求,请求获取网页内容。HTTP 请求会通过 TCP 协议建立连接,然后通过该连接传输数据。服务器收到请求后,会通过 HTTP 协议响应客户端,将网页内容发送回客户端。这个过程中,HTTP 协议负责定义客户端和服务器之间通信的消息格式,而 TCP 协议负责建立和维护网络连接,确保数据能够正确传输。
总之,HTTP 和 TCP 都参与数据传输,但它们各自有其独特的用途,并且彼此相关。HTTP 是一种应用层协议,用于定义客户端和服务器之间通信的消息格式;而 TCP 是一种传输层协议,用于建立和维护网络连接,确保数据能够正确传输