在介绍 Socket.io 之前,首先需要说一说什么是 WebSocket。
什么是WebSocket?
WebSocket是一种让客户端和服务器之间进行双向实时通讯的技术,也是HTML5的的一个规范协议,本质是基于TCP协议,它通过http/https发送一条特殊的请求进行握手建立一个TCP连接,此后客户端和服务器之间便可以通过次连接进行双向通讯。
为什么要用WebSocket?
一直以来,http是无状态,单向通讯的,即客户端请求一次,服务器回复一次。如果想让服务器消息及时下发到客户端,需要采用类似于轮询的机制,下面介绍两种常见方式:
- ajax 轮询
ajax轮询的原理很简单,就是让浏览器(客户端)定时(隔几秒)向服务器发送一次请求,浏览器就收服务器返 回的数据更新显示出来,然后重复这一过程:
- Long Polling
Long Polling与ajax轮询的原理差不多,不过它算是polling的一种改进。客户端发送请求到服务器,服务端并不立即响应返回客户端,而是保持这次连接,当有新的数据时候,在返回客户端展示,并重复该过程。如果服务器长时间没有数据更新,这个请求会超时并且客户端收到消息后,重新发送新的请求。
从上面可以看出,两种方式的弊端是不断发送http请求,然后等服务器的处理。
ajax轮询方式-假如服务器短时间没有数据更新,客户端仍定时发送请求,服务器仍然发送老数据,这样做既浪费宽带又浪费CPU的占有率。
Long Polling方式一定程度上解决了宽带浪费和CPU占有率的情况,但是如果服务器的数据更新过快,服务器在返回一次数据给客户端之后,只能等客户端再发送一次请求之后,才能发送下一个数据包给客户端,如果再网络拥塞的情况下,这种情况是很多人不能接受的。
再这样的情况下,一种新的网络协议,可以支持客户端和服务端双向通讯的协议 WebSocket 因应而生了。
WebSocket协议
WebSocket 协议是一种持久化的双向通信协议,它建立在TCP之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大的不同点有
- 服务端可以主动向客户端推送数据,客户端也可以主动向服务器推送数据
- 服务器与客户端之间建立一个非http的双向通道。这个通道是实时的,也是永久的(除非被关闭)
WebSocket与http、tcp的关系
WebSocket在建立握手连接时,请求体是通过http协议传输的,连接成功后真正的数据传输是不需要http协议参与的。
WebSocket API
WebSocket对象作为一个构造函数,通过new WebSocket('ws://xxxx.com') 客户端会与服务器进行连接 。
浏览器支持
WebSocket是HTML5新提出的规范,从上面得知虽然主流的浏览器都已经支持,但如果低版本或部分浏览器仍存在兼容问题。
为了兼容所有浏览器,提供统一的编程写法。SocketIO将WebSocket、AJAX和其他通讯方式全部封装成统一通讯接口。也就是说,我们在使用SocketIO时候,不在考虑担心兼容问题,底层会自动选用最佳通讯方式,因此说Web是SocketIO的子集。
Socket.io 介绍
SocketIO是一个完全由JavaScript实现、基于Node.js、支持WebSocket协议用于实时通讯、跨平台、解决众多浏览器兼容开源库,包括客户端JavaScript和服务器的Node.js
Socket.io支持的通讯方式
- WebSocket
- Adobe Flash Socket
- AJAX long-polling
- AJAX multipart streaming
- Forever IFrame
- JSONP polling
Socket.io的使用
服务端可以使用node.js express框架搭建
引入
服务端:
npm install --save socket.io
浏览器端(CDN加速):
cdnjs: https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.2/socket.io.min.js
vue:
npm install vue-socket.io --save
Socket实例(服务端)
安装 Socket.IO之后,现在就可以初始化服务器了。选项的完整列表可以在下面找到
通过上面两种方式导入并初始化IO,参数 httpServer 是要绑定的服务器,options 是初始化的一些配置,常用配置如下:
path
默认值:/socket.io/
描述:服务器端捕获的路径的名称,同时服务器和客户端值必须匹配
pingTimeout
默认值:20000ms
描述:此值用于心跳机制,该机制定期检查服务器和客户端之间的连接是否仍然存在,服务器发送一个 ping,如果客户机在pingTimeout ms 中没发送pong应答,服务器将认为连接已关闭。
pingInterval
默认值:25000ms
描述:类似地,如果客户机在 pingInterval + pingTimeout ms 内没有从服务器接收 ping,那么客户机也会认为连接已经关闭
maxHttpBufferSize
默认值:1e6 (1 MB)
描述:单个消息可以有多少个字节。您可以根据自己的需要增加或减少这个值。
transports
默认值:["polling", "websocket"]
描述:首先使用 HTTP建立长轮询连接,然后尝试升级到 WebSocket
cors
默认值:-
描述:将转发到 origin 模块的选项列表,更多信息https://www.npmjs.com/package/cors
socket.io事件(服务端)
Socket实例提供了默认事件(如:connection, disconnect)。另外,Socket.IO允许发送并接收自定义事件。
- 监听客户端连接,回调函数会传递本次连接的socke
- 监听客户端断开,回调函数参数是断开的原因
- 给所有客户端广播消息,eventName客户端监听注册事件,data返回数据
- 给指定的客户端发送自定义事件
- 接收客户端发送的自定义事件
房间(room)
房间是 Socket.IO 提供的一个非常好用的功能。房间相当于为指定的一些客户端提供了一个命名空间,所有在房间里的广播和通信都不会影响到房间以外的客户端。
- 使用 join() 方法将 socket 加入房间
- 使用 leave() 方法离开房间:
- 向房间中除了当前 socket 的其他 socket 发送消息
- 向房间中所有的 socket 发送消息
命名空间
通过命名空间 of() 可以为 Socket.IO 设置子程序。默认命名空间为 “/”,Socket.IO 默认连接该路径。通过路径名(例如:/chat)标识的给定范围下连接的套接字池,且各个路径下的连接池不干扰。
Socket实例(客户端)
如果你的前端服务器和你的服务器在同一个域名,你可以简单地使用:
建立有命名空间的 socket 连接
监听服务器消息
向服务器发送消息
监听 socket 断开与重连事件
注:如果你使用Node.js做服务端,那么毫无疑问你该选择Socket.IO,它本省就是从Node.js开始的,但如果是使用Java做服务端,同时又恰好使用Spring Framework作为框架,那么推荐使用SockJS+Stomp
简单聊天室
流程:
- 创建socket服务器
- 浏览器建立socket连接
- 进入首页随机生成头像,输入用户名和房间号进入房间
- 发送数据与房间内好友聊天
- 支持数据发送,文本、图片和视频
node端代码
浏览器 socket 代码
socket.ioAPI文档参考: https://socket.io/
查看api兼容性参考:https://www.caniuse.com/
深入了解websocket: https://www.zhihu.com/question/20215561
项目git 连接:https://github.com/Arrizo/sockets