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

Posted 诺浅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了谈谈http/tcp的长连接和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,交互模式依然是一问一答的模式,相较没开启Keep-alive只是省略了每次连接的关闭和打开操作。我理解是由于tcp交互之前是需要三次握手的,而开启了Keep-alive只是节省了握手这个过程(不对请指出)。

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

上面讲述了http协议的缺点,那么如果我们需要服务器状态变化的时候能够主动通知客户端,我们有没有什么办法呢?

这种需求很常见,比如微信扫描PC页面上的二维码登录,在扫描完了之后页面就会跳转,那么页面是处于客户端PC上,他是如何知道我们通过手机扫描了这个二维码的呢?这其实就是一个服务端通知客户端的很典型的例子,微信后台接收到手机微信扫描完成的

消息进而通知客户端PC页面进行跳转。这就可以用到websocket,当然只是说websocket可以实现这个功能,并不是说是唯一的解决方案,也不是说微信是使用这个技术来实现的,不要杠~

关于websocket

websocket的协议是在TCP/IP协议簇的应用层,和http在同一层,也是应用层的协议,但是它是一种双向通信协议。


上图对比可以看出,相对于传统 HTTP每次请求-应答都需要客户端与服务端建立连接的模式,WebSocket是类似SocketTCP长连接的通讯模式,一旦 WebSocket 连接建立后,后续数据都以帧序列的形式传输。在连接断开前,不需要重新发起连接请求。

在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。

Websocket的流程大概是以下几步

  1. 客户端-服务端建立TCP连接,三次握手。这是通信的基础,传输控制层,若失败后续都不执行。
  2. TCP连接成功后,客户端通过HTTP协议向服务器传送WebSocket支持的版本号等信息。这一步称为开始前的HTTP握手
  3. 服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据,此时回馈的数据中会指明服务器的WebSocket支持的版本号等信息
  4. 当客户端收到了连接成功的消息后,通过TCP通道进行传输通信。

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

一次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-KeyWebSocket 客户端发送的一个 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其实并不是一个协议,而是为了方便使用TCPUDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

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

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

我觉得上诉话并没有把二者的区别说清楚,简单来说Socket只是一个使用tcp的接口而已,tcp只是协议,他需要有API才能使用他,而socket提供了这些api。

WebSocket与Socket详细区别

WebSocket与html5的关系

WebSocket APIHTML5 标准的一部分,但这并不代表 WebSocket 一定要用在 HTML5 中,或者只能在基于浏览器的应用程序中使用。
实际上,许多语言、框架和服务器都提供了 WebSocket 支持,例如:

  • 基于 C 的 libwebsocket.org
  • 基于 Node.js 的 Socket.io
  • 基于 Python 的 ws4py
  • 基于 C++ 的 WebSocket++
  • Apache 对 WebSocket 的支持:Apache Module mod_proxy_wstunnel
  • nginx 对 WebSockets 的支持:NGINX as a WebSockets Proxy 、 NGINX Announces Support for WebSocket Protocol 、WebSocket proxying
  • lighttpd 对 WebSocket 的支持:mod_websocket

写在最后

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

参考:https://www.cnblogs.com/Javi/p/9303020.html

以上是关于谈谈http/tcp的长连接和websocket的长连接的主要内容,如果未能解决你的问题,请参考以下文章

分析 HTTP,TCP 的长连接和短连接以及 socket

谈谈HTTP协议中的长连接,短连接

HTTP1.1之后的长连接和WebSocket的长连接之间的区别

http中长连接和websocket的长连接的区别

http中长连接和websocket的长连接的区别(转)

网络协议中HTTP,TCP,UDP,Socket,WebSocket的优缺点/区别