我拆过的坑cycx

查询一下!

谈谈http的长连接和websocket的长连接

HTTP 协议的“缺陷”

了解http的人都知道,HTTP 协议有一个缺陷:通信只能由客户端发起。例如,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息的, 这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦,客户端只能使用"轮询"的方式,即每隔一段时间,就发出一个请求,请求服务器有没有状态变化 。可见轮询的效率低,非常浪费资源。


在http1.1中,默认开启了一个叫Keep-alive的参数,官方的说法是可以用这个来作为长连接。你是否以为既然客户端与服务器保持了长连接,服务器就能主动给客户端推送消息呢?


关于Keep-alive的缺点

Keep-alive的确可以实现长连接,但是这个长连接是有问题的,本质上依然是客户端主动发起-服务端应答的模式,是没法做到服务端主动发送通知给客户端的。也就是说,在一个HTTP连接中,客户端可以发送多个Request,接收多个Response。但是请记住 Request = Response , 在HTTP中永远是这样,一个request只能有一个response。而且这个response也是被动的,不能主动发起。放上一张图,图左为没开启Keep-alive,图右为开启了Keep-alive,可以看出依然是一问一答的模式,向较左边只是省略了每次的关闭和打开操作。




需要注意的是Keep-alive是指不需要多次建立连接,而非http2.0里面的多路复用,多路复用的意思是客户端可以同时向服务器端发送多个请求,服务器端也可以同时响应多个Response.




关于websocket

那么如果我们需要服务器状态变化的时候能够主动通知客户端,我们有没有什么办法呢?这就要用到websocket。



上图对比可以看出,相对于传统 HTTP每次请求-应答都需要客户端与服务端建立连接的模式,WebSocket是类似 Socket 的 TCP 长连接的通讯模式,一旦 WebSocket 连接建立后,后续数据都以帧序列的形式传输。在客户端断开 WebSocket 连接或 Server 端断掉连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。


WebSocket API 是 HTML5 标准的一部分, 但这并不代表 WebSocket 一定要用在 HTML 中,或者只能在基于浏览器的应用程序中使用。


在WebSocket中,只需要服务器和浏览器通过TCP协议进行一个握手的动作,然后单独建立一条TCP的通信通道进行数据的传送。WebSocket同HTTP一样也是应用层的协议,但是它是一种双向通信协议,是建立在TCP之上的。websocket的流程大概是以下几步



浏览器、服务器建立TCP连接,三次握手。这是通信的基础,传输控制层,若失败后续都不执行。

TCP连接成功后,浏览器通过HTTP协议向服务器传送WebSocket支持的版本号等信息。(开始前的HTTP握手)

服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据。

当收到了连接成功的消息后,通过TCP通道进行传输通信。


也就是说WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要TCP协议的。


看看一次websocket的握手请求与应答的报文


WebSocket 客户端连接报文


GET /webfin/websocket/ HTTP/1.1

Host: localhost

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==

Origin: 

http://localhost

:8080

Sec-WebSocket-Version: 13

 

可以看到,客户端发起的 WebSocket 连接报文类似传统 HTTP 报文,”Upgrade:websocket”参数值表明这是 WebSocket 类型请求,“Sec-WebSocket-Key”是 WebSocket 客户端发送的一个 base64 编码的密文,要求服务端必须返回一个对应加密的“Sec-WebSocket-Accept”应答,否则客户端会抛出“Error during WebSocket handshake”错误,并关闭连接。


服务端收到报文后返回的数据格式类似:


WebSocket 服务端响应报文


HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=

 

“Sec-WebSocket-Accept”的值是服务端采用与客户端一致的密钥计算出来后返回客户端的,“HTTP/1.1 101 Switching Protocols”表示服务端接受 WebSocket 协议的客户端连接,经过这样的请求-响应处理后,客户端服务端的 WebSocket 连接握手成功, 后续就可以进行 TCP 通讯了。


WebSocket与Socket的关系

Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。


Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。


当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。


WebSocket则是一个典型的应用层协议。


觉得本文不错的朋友,点个赞吧,你的赞是我持续写作的动力。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Powered By Z-BlogPHP 1.7.3

Copyright Your WebSite.Some Rights Reserved.