http1.0的时候,一个http请求的生命周期是客户端发起请求,服务器响应,断开连接。但是大家知道tcp协议的缺点就是,三次握手需要时间,再加上慢开始等特性,每一个http请求都这样的话,效率就很低。http1.1的时候,默认开启了长连接(客户端请求中设置了keep-alive头),服务器处理一个请求后,不会立刻关闭连接,而是会等待一定的时间。如果没有请求才关闭连接。这样浏览器不仅可以在一个tcp连接中,不断地发送请求(服务器也会限制一个连接上可以处理的请求阈值),甚至可以一次发很多个请求。这就是http1.1的管道化(pipeline)技术。但是他也有个问题,因为对于基于http协议的客户端来说,虽然他可以发很多请求出去,但是当一个请求对于的回包回来时,他却无法分辨是属于哪个请求的。所以回包只能按请求顺序返回,这就引来了另一个问题-线头阻塞(Head-of-Link Blocking)。并且http1.1虽然支持长连接,但是他不支持服务端推送(push)的能力。如果服务器有数据要给客户端,也只能等着客户端来取(pull)。来到了http2.0,不仅实现了服务器推送,还使用了帧(iframe),流(stream)等技术解决了线头阻塞的问题,http2.0在一个tcp连接中,可以同时发送多个http请求,每个请求是一个流,一个流可以分成很多帧,有了标记号,服务器可以随便发送回包,客户端收到后,根据标记,重新组装就可以。以上是http协议的关于请求的一些发展,而websocket就服务端推送提供了另外一种解决方案。他本质上是在tcp协议上封装的另一种应用层协议(websocket协议)。因为他是基于tcp的,所以服务端推送自然不是什么难题。但是在实现上,他并不是直接连接一个tcp连接,然后在上面传输基于websocket协议的数据包。他涉及到一个协议升级(交换)的过程。大家看看这个过程。1 客户端发送协议升级的请求。在http请求加上下面的http头2 服务器如果支持websocket协议的话,会返回101状态码表示同意协议升级,并且支持各种配置(如果服务器不支持某些功能或版本,或告诉客户端,客户端可以再次发送协议升级的请求)。服务会返回形如下面的http头(可以参考websocket协议)。3 这样就完成了协议的升级,后续的数据通信,就是基于tcp连接之上,使用websocket协议封装的数据包。下面大家通过wireshark来了解这个过程。首先大家启动一个服务器(ip:192.168.8.226)。大家可以直接在浏览器控制台进行测试这时候,大家看看wireshark的包。首先看前面三条记录,这是tcp三次握手的数据包。这个大家都了解了,就不展示。接着看第四条记录。展开后如下。大家看到建立tcp连接后,浏览器发了一个http请求,并带上了几个websocket的数据包。接着看下面的一条。服务返回了同意升级协议或者说交换协议。从服务器代码中大家看到,在建立连接的时候大家给浏览器推送了一个get it的字符串。继续看上面的记录。这就是服务器给浏览器推送的基于websocket协议的数据包。具体每个字段什么意思,参考websocket协议就可以。继续往下看一条记录是针对服务器推送的数据包的一个tcp的ack。最后大家可以顺便看看最后三条写着keep-alive的记录。这就是之前文章里讲到的tcp层的keep-alive。因为大家一直没有数据传输,所以tcp层会间歇性地发送探测包。大家可以看看探测包的结构。有一个字节的探测数据。如果这时候大家发送一个数据包给服务器,又是怎样的呢。白色背景的三条数据,分别是浏览器发送给服务器的数据,服务器推送回来的数据。tcp的ack。大家发现,服务器给浏览器推送的时候,浏览器会发送ack,但是浏览器给服务器发送的时候,服务器貌似没有返回ack。下面大家看看为什么。首先大家看浏览器发出的包。再看看服务器给浏览器推送的数据包。大家发现服务器(tcp)推送消息的时候把ack也带上了。而不是发送两个tcp包。这就是tcp的机制。tcp不会对每个包都发ack,他会累积确认(发ack),以减少网络的包,但是他也需要保证尽快地回复ack,否则就会导致客户端触发超时重传。tcp什么时候发送确认呢?比如需要发送数据的时候,或者超过一定时间没有收到数据包,或者累积的确认数量达到阈值等。既然研究了tcp,大家不妨多研究点,大家看一下,如果这时候关闭服务器会怎样。服务器会发送一个重置包给浏览器,告诉他需要断开连接。继续,如果是浏览器自己调用close去关闭连接会怎样。大家看到websocket首先会发送一个FIN包给服务器,然后服务器也会返回一个FIN包,然后才开始真正的四次挥手过程。并且四次挥手的第一个fin包是服务器发的。大家再来看看安全版本的websocket。大家启动一个https服务器。然后在浏览器控制台执行。然后来看看wireshark。首先建立tcp连接,然后建立tls连接。后续的数据通信就可以基于加密来进行了。不再重复。后续分析tls协议的时候再分析。经过一系列的分析,大家对websocket协议应该有了更多的了解,最后再说一个关于websocket的点。大家发现如果在websocket连接上,一直不通信的话,websocket连接所维持的时间是依赖tcp实现的。因为大家发现tcp层会一直发送探测包。达到阈值之后,连接就会被断开。所以大家想维持websocket连接的话,需要自己去发送心跳包,比如ping,pong。总结:本文分析了websocket的基本原理,但不涉及协议的内容,如需了解协议的内容,可以参考rfc文档。
如果觉得《mysql中去重查询 WebSocket是什么原理 – 数据库 – 前端 mysql alert 索引》对你有帮助,请点赞、收藏,并留下你的观点哦!