webSocket

1、历史

没有webSocket的时代,我们是如何来处理一些实时场景的?

图中user1发送http请求经过服务器,服务器进行转发,但是http请求要求服务器不能主动,只能被动,必须user2去请求服务器,user2不知道有人给他发消息,主要问题就是user2不能主动

由于HTTP协议是请求-响应模式,请求必须在前,响应必须在后,这就导致了服务器无法「主动」的把消息告诉客户端。

当然终极解决方案自然是WebSocket,但了解过去的一些做法、参观前辈们经历的痛苦还是有益的。

1.1短轮询short polling

是一种"话唠式"的方式,客户端每隔一小段时间就向服务器请求一次,询问有没有新消息

  • 会产生大量无意义的请求
  • 会频繁打开关闭连接
  • 实时性并不高

1.2长轮询long polling

发送过去没有新消息不响应,等到有新消息后再响应,客户端马上发起下一次请求

优点:

  • 使得每一次请求和响应都是有意义

缺点:

  • 客户端长时间收不到响应会导致超时,从而主动断开和服务器的连接(Ajax有超时时间,主动断开了TCP时间,可以在每次超时结束后再次发起ajax请求,虽然使得每一次请求和响应变得无意义,但比短轮询好多了)
  • 由于客户端过早的请求了服务器,服务器不得不挂起这个请求知道新消息的出现,这会让服务器长时间的占用资源却没什么实际的事情可做

1.3WebSocket

1.3.1简介

伴随着HTML5出现的WebSocket,从协议上赋予了服务器主动推送消息的能力

从上图可以看出:

  • WebSocket也是建立在TCP协议(图中绿色)之上的,利用的是TCP全双工通信(任意互发消息,http是半双工,客户端可以请求服务器,但是有先后顺序)的能力
  • 使用WebSocket,会经历两个阶段:握手阶段(是在TCP三次握手之后)、通信阶段

虽然优于轮询方案,但WebSocket仍然是有缺点的:

  • 兼容性
    WebSocket是HTML5新增的内容,因此古董版本的浏览器并不支持
  • 维持TCP连接需要耗费资源
    对于那些消息量少的场景,维持TCP连接确实会造成资源的浪费
    为了充分利用TCP连接的资源,在使用了WebSocket的页面,可以完全放弃ajax,都用WebSocket进行通信,当然这会带来程序设计上的一些问题,需要权衡。
1.3.2握手

WebSocket协议是一个高扩展性的协议,详细内容会比较复杂,这里仅讲解面试中会问到的握手协议

当客户端需要和服务器使用WebSocket进行通信时,首先会使用HTTP协议 完成一次特殊的请求-响应,这一次请求-响应就是WebSocket握手

在握手阶段,首先由客户端向服务器发送一个请求,请求地址格式如下:

javascript 复制代码
# 使用HTTP
ws://mysite.com/path
# 使用HTTPS
wss://mysite.com/path

请求头如下:

javascript 复制代码
Connection: Upgrade /* 嘿,后续咱们别用HTTP了,升级吧 */
Upgrade: websocket /* 我们把后续的协议升级为websocket */
Sec-WebSocket-Version: 13 /* websocket协议版本就用13好吗? */
Sec-WebSocket-Key: YWJzZmFkZmFzZmRhYw== /* 暗号:天王盖地虎 */

服务器如果同意,就应该响应下面的消息

javascript 复制代码
HTTP/1.1 101 Switching Protocols /* 换,马上换协议,消息码101面试要考,表示切换协议 */
Connection: Upgrade /* 协议升级了 */
Upgrade: websocket /* 升级到websocket */
Sec-WebSocket-Accept: ZzIzMzQ1Z2V3NDUyMzIzNGVy /* 暗号:小鸡炖蘑菇(天王盖地虎生成出来的) */
1.3.3面试题
  1. webSocket 协议是什么,能简述一下吗?

    websocket 协议 HTML5 带来的新协议,相对于 http,它是一个持久连接的协议,它利用 http 协议完成握手,然后通过 TCP 连接通道发送消息,使用 websocket 协议可以实现服务器主动推送消息。

    首先,客户端若要发起 websocket 连接,首先必须向服务器发送 http 请求以完成握手,请求行中的 path 需要使用ws:开头的地址,请求头中要分别加入upgrade、connection、Sec-WebSocket-Key、Sec-WebSocket-Version标记

    然后,服务器收到请求后,发现这是一个 websocket 协议的握手请求,于是响应行中包含Switching Protocols,同时响应头中包含upgrade、connection、Sec-WebSocket-Accept标记

    当客户端收到响应后即可完成握手,随后使用建立的 TCP 连接直接发送和接收消息。

  2. webSocket 与传统的 http 有什么优势

    当页面中需要观察实时数据的变化(比如聊天、k 线图)时,过去我们往往使用两种方式完成

    第一种是短轮询,即客户端每隔一段时间就向服务器发送消息,询问有没有新的数据

    第二种是长轮询,发起一次请求询问服务器,服务器可以将该请求挂起,等到有新消息时再进行响应。响应后,客户端立即又发起一次请求,重复整个流程。

    无论是哪一种方式,都暴露了 http 协议的弱点,即响应必须在请求之后发生,服务器是被动的,无法主动推送消息。而让客户端不断的发起请求又白白的占用了资源。

    websocket 的出现就是为了解决这个问题,它利用 http 协议完成握手之后,就可以与服务器建立持久的连接,服务器可以在任何需要的时候,主动推送消息给客户端,这样占用的资源最少,同时实时性也最高。

  3. 前端如何实现即时通讯?

    短轮询。即客户端每隔一段时间就向服务器发送消息,询问有没有新的数据

    长轮询,发起一次请求询问服务器,服务器可以将该请求挂起,等到有新消息时再进行响应。响应后,客户端立即又发起一次请求,重复整个流程。

    websocket,握手完毕后会建立持久性的连接通道,随后服务器可以在任何时候推送新消息给客户端

1.3.4API
javascript 复制代码
const ws = new WebSocket('ws://localhost:8818');//完成握手
ws.onopen = function(e) {
console.log("连接服务器成功");
}
ws.onclose = function(e) {
console.log("服务器关闭");
}
ws.onerror = function() {
console.log("连接出错");
}
ws.onmessage = function(e){
const time = new Date();
console.log(time+"收到的消息:"+e.data);
}

//发送信息到服务器,发送后不一定有响应
ws.send('your message')
ws.readyState//0正在连接,1已连接,2正在关闭,3已关闭
1.3.5SocketIO

消息一多都在onmessage接收,http请求是通过path解决,请求接口名不同,获取内容不同



如何使用?

javascript 复制代码
const socket=io("ws://localhost:9528")
socket.on('$updateUser',(users)=>{
	log(users)
})
相关推荐
‘’林花谢了春红‘’6 分钟前
计算机网络习题(第5章 网络层 第6章 传输层)
网络·计算机网络
哎呦不错哦.13 分钟前
简单园区网拓扑实验
网络·智能路由器
hgdlip38 分钟前
手机IP地址:定义、查看与切换方法
网络协议·tcp/ip·智能手机
dengjiayue4 小时前
tcp 的重传,流量控制,拥塞控制
网络协议·tcp/ip
咕德猫宁丶5 小时前
探秘Xss:原理、类型与防范全解析
java·网络·xss
黑子哥呢?5 小时前
Linux---防火墙端口设置(firewalld)
linux·服务器·网络
hellojackjiang20116 小时前
开源轻量级IM框架MobileIMSDK的鸿蒙NEXT客户端库已发布
网络·即时通讯·im开发·mobileimsdk-鸿蒙端
WebDeveloper20017 小时前
如何使用美国域名中心US Domain Center和WordPress创建商业网站
运维·服务器·css·网络·html
车载诊断技术8 小时前
电子电气架构 --- 什么是EPS?
网络·人工智能·安全·架构·汽车·需求分析
KevinRay_8 小时前
Python超能力:高级技巧让你的代码飞起来
网络·人工智能·python·lambda表达式·列表推导式·python高级技巧