文章目录
一、什么是WebSocket?
WebSocket是HTML5新增的协议,它诞生的目的就是在浏览器和服务器之间建立一个不受限的双向通信的通道,它并不是全新的协议,是利用了http协议来建立连接的。
websocket是一种自然的全双工、双向、单套接字连接,使用websocket,http请求就变成打开websocket连接的单一请求,websocket减少了延迟,一旦建立连接,服务器可以在消息可用时发送他们。和轮询不同,websocket只发出一个请求。服务器不需要等待来自客户端的请求。客户端可以在任何时候向服务器发送消息。相比轮询,不管是否有可用消息,每隔一段时间都发送一个请求,单一请求大大减少了延迟。
二、WebSocket的特点
(1)服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
(2)建立在 TCP 协议之上,服务器端的实现比较容易。
(3)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(4)数据格式比较轻量,性能开销小,通信高效。
(5)可以发送文本,也可以发送二进制数据。
(6)没有同源限制,客户端可以与任意服务器通信。
(7)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
ws://example.com:80/some/path
三、为什么需要WebSocket?
1、与性能相关;WebSocket使实时通信更加有效。WebSocket能节约带宽、CPU资源并减少延迟
2、与简洁性相关;WebSocket是web上客户端和服务器之间的通信变得更加简单
3、与标准相关;WebSocket是一个低层网络协议,你可以在它的基础上构建其他标准协议
4、与HTML5相关;WebSocket是为HTML5应用程序提供高级功能,以便与其他平台竞争所做努力的一部分,他是HTML5平台的关键组件,也是开发人员的强大工具
5、简单的说你需要WebSocket来构建世界级的Web应用程序。WebSocket解决了使HTTP不适合于实时通信的主要不足之处,WebSocket的异步、双向通信模式是对Internet上的传输层协议提供的总体灵活性的回报
四、WebSocket 与 HTTP 的区别
WebSocket 与 HTTP 的关系图:
相同点: 都是一样基于TCP的,都是可靠性传输协议。都是应用层协议。
联系: WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。
下面一张图说明了 HTTP 与 WebSocket 的主要区别:
不同点:
1、 WebSocket 是双向通信协议,模拟 Socket 协议,可以双向发送或接受信息,而 HTTP 是单向的;
2、 WebSocket 是需要浏览器和服务器握手进行建立连接的,而 http 是浏览器发起向服务器的连接。
3、 虽然 HTTP/2 也具备服务器推送功能,但 HTTP/2 只能推送静态资源,无法推送指定的信息。
五、Websocket的优缺点
优点:
1、WebSocket协议一旦建议后,互相沟通所消耗的请求头是很小的
2、服务器可以向客户端推送消息了
3、更好的二进制支持。WebSocket 定义了二进制帧,相对 HTTP,可以更轻松地处理二进制内容
4、可以支持扩展。WebSocket 定义了扩展,用户可以扩展协议、实现部分自定义的子协议。
缺点:
1、少部分浏览器不支持,浏览器支持的程度与方式有区别(IE10)
六、WebSocket应用场景
1、即时聊天通信
2、多玩家游戏
3、在线协同编辑/编辑
4、实时数据流的拉取与推送
5、体育/游戏实况
6、实时地图位置
7、即时Web应用程序:即时Web应用程序使用一个Web套接字在客户端显示数据,这些数据由后端服务器连续发送。在WebSocket中,数据被连续推送/传输到已经打开的同一连接中,这就是为什么WebSocket更快并提高了应用程序性能的原因。例如在交易网站或比特币交易中,这是最不稳定的事情,它用于显示价格波动,数据被后端服务器使用Web套接字通道连续推送到客户端。
8、游戏应用程序:在游戏应用程序中,你可能会注意到,服务器会持续接收数据,而不会刷新用户界面。屏幕上的用户界面会自动刷新,而且不需要建立新的连接,因此在WebSocket游戏应用程序中非常有帮助。
9、聊天应用程序:聊天应用程序仅使用WebSocket建立一次连接,便能在订阅户之间交换,发布和广播消息。它重复使用相同的WebSocket连接,用于发送和接收消息以及一对一的消息传输。
不能使用WebSocket的场景
如果我们需要通过网络传输的任何实时更新或连续数据流,则可以使用WebSocket。如果我们要获取旧数据,或者只想获取一次数据供应用程序使用,则应该使用HTTP协议,不需要很频繁或仅获取一次的数据可以通过简单的HTTP请求查询,因此在这种情况下最好不要使用WebSocket。
注意:如果仅加载一次数据,则RESTful Web服务足以从服务器获取数据。
七、客户端的API
1、WebSocket构造函数
WebSocket 对象作为一个构造函数,用于新建 WebSocket 实例。
var ws = new WebSocket('ws://localhost:8080');
执行上面语句之后,客户端就会与服务器进行连接。
实例对象的所有属性和方法清单,参见这里。
2、webSocket.readyState
readyState属性返回实例对象的当前状态,共有四种。
- CONNECTING:值为0,表示正在连接。
- OPEN:值为1,表示连接成功,可以通信了。
- CLOSING:值为2,表示连接正在关闭。
- CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
下面是一个示例。
switch (ws.readyState) {
case WebSocket.CONNECTING:
// do something
break;
case WebSocket.OPEN:
// do something
break;
case WebSocket.CLOSING:
// do something
break;
case WebSocket.CLOSED:
// do something
break;
default:
// this never happens
break;
}
3、webSocket.onopen
实例对象的onopen属性,用于指定连接成功后的回调函数。
ws.onopen = function () {
ws.send('Hello Server!');
}
如果要指定多个回调函数,可以使用addEventListener方法。
ws.addEventListener('open', function (event) {
ws.send('Hello Server!');
});
4、webSocket.onclose
实例对象的onclose属性,用于指定连接关闭后的回调函数。
ws.onclose = function(event) {
var code = event.code;
var reason = event.reason;
var wasClean = event.wasClean;
// handle close event
};
ws.addEventListener("close", function(event) {
var code = event.code;
var reason = event.reason;
var wasClean = event.wasClean;
// handle close event
});
5、webSocket.onmessage
实例对象的onmessage属性,用于指定收到服务器数据后的回调函数。
ws.onmessage = function(event) {
var data = event.data;
// 处理数据
};
ws.addEventListener("message", function(event) {
var data = event.data;
// 处理数据
});
注意,服务器数据可能是文本,也可能是二进制数据(blob对象或Arraybuffer对象)。
ws.onmessage = function(event){
if(typeof event.data === String) {
console.log("Received data string");
}
if(event.data instanceof ArrayBuffer){
var buffer = event.data;
console.log("Received arraybuffer");
}
}
除了动态判断收到的数据类型,也可以使用binaryType属性,显式指定收到的二进制数据类型。
// 收到的是 blob 数据
ws.binaryType = "blob";
ws.onmessage = function(e) {
console.log(e.data.size);
};
// 收到的是 ArrayBuffer 数据
ws.binaryType = "arraybuffer";
ws.onmessage = function(e) {
console.log(e.data.byteLength);
};
6、webSocket.onerror
实例对象的onerror属性,用于指定报错时的回调函数。
socket.onerror = function(event) {
// handle error event
};
socket.addEventListener("error", function(event) {
// handle error event
});
八、WebSocket库
websocket库目前比较热门的是ws和socket.io,他们都可以单独作为websocket服务器,也可以挂到express和koa框架,同时提供web和websocket服务。不同的是ws客户端不支持浏览器,需要用户自行封装websocket。而socket.io客户端对浏览器有良好的支持。socket.io客户端封装的websocket请求自带id,服务器可以根据id区分客户端,进行精准推送。