• Http请求的TCP连接


    我们一直认为,HTTP连接分为长连接和短连接,而我们现在常用的都是HTTP1.1,因此我们用的都是长连接。

      这句话其实只对了一半,我们现如今的HTTP协议,大部分都是1.1的,因此我们平时用的基本上都是长连接。但是前半句是不对的,HTTP协议根本没有长短连接这一说,也正因为误解了这个,导致LZ对于长连接一直不明不白,始终不得其要领,具体下面一段会说到。

      网络上很多文章都是误人子弟,根本没有说明白这个概念。这里LZ要强调一下,HTTP协议是基于请求/响应模式的,因此只要服务端给了响应,本次HTTP连接就结束了,或者更准确的说,是本次HTTP请求就结束了,根本没有长连接这一说。那么自然也就没有短连接这一说了。

      之所以网络上说HTTP分为长连接和短连接,其实本质上是说的TCP连接。TCP连接是一个双向的通道,它是可以保持一段时间不关闭的,因此TCP连接才有真正的长连接和短连接这一说

      其实知道了以后,会觉得这很好理解。HTTP协议说到底是应用层的协议,而TCP才是真正的传输层协议,只有负责传输的这一层才需要建立连接。

      一个形象的例子就是,拿你在网上购物来说,HTTP协议是指的那个快递单,你寄件的时候填的单子就像是发了一个HTTP请求,等货物运到地方了,快递员会根据你发的请求把货物送给相应的收货人。而TCP协议就是中间运货的那个大货车,也可能是火车或者飞机,但不管是什么,它是负责运输的,因此必须要有路,不管是地上还是天上。那么这个路就是所谓的TCP连接,也就是一个双向的数据通道。

      因此,LZ现在甚至觉得,“HTTP连接”这个词就不应该出现,它只是一个应用层的协议,根本就没有所谓的连接这一说,就像FTP也是应用层的协议,但是你有听说过FTP连接吗?(恩,好像是听过,-_-,但你现在知道了,其实所谓的FTP连接,严格来说,依旧是TCP连接)

      实际上,说HTTP请求和HTTP响应会更准确一些,而HTTP请求和HTTP响应,都是通过TCP连接这个通道来回传输的。

      不管怎么说,一定要务必记住,长连接是指的TCP连接,而不是HTTP连接。

      长连接是为了复用,这个在之前LZ就明白。那既然长连接是指的TCP连接,也就是说复用的是TCP连接。那这就很好解释了,也就是说,长连接情况下,多个HTTP请求可以复用同一个TCP连接,这就节省了很多TCP连接建立和断开的消耗。

      比如你请求了博客园的一个网页,这个网页里肯定还包含了CSS、JS等等一系列资源,如果你是短连接(也就是每次都要重新建立TCP连接)的话,那你每打开一个网页,基本要建立几个甚至几十个TCP连接,这浪费了多少资源就不用LZ去说了吧。

      但如果是长连接的话,那么这么多次HTTP请求(这些请求包括请求网页内容,CSS文件,JS文件,图片等等),其实使用的都是一个TCP连接,很显然是可以节省很多消耗的。

      另外,最后关于长连接还要多提一句,那就是,长连接并不是永久连接的。如果一段时间内(具体的时间长短,是可以在header当中进行设置的,也就是所谓的超时时间),这个连接没有HTTP请求发出的话,那么这个长连接就会被断掉。

    下面是一些实验数据:

      一次HTTP请求的连接及请求响应过程,实际上,我门观察一次网页请求抓取的所有包,发现其中一共建立了4个TCP连接,在下图中显示了其中的2个连接的握手信息。

    这4个连接分别用在了获取页面中引入的样式表、样式表中的字体图片等信息。截取部分依赖:

      实际上,一个页面所引用的所有组件,包括样式表、图片、脚本等都是一次HTTP请求,从Network中可以看出本次页面请求一共进行了包含HTML文档在内的7次HTTP请求:

    这些请求分在4个TCP连接中进行。具体在抓包中有所体现,举一个例子来说吧:

      这里对页面中引用的normalize.css就是通过另一个TCP连接获取的,通过端口号可以区分,这里是建立在60546端口的TCP连接,不同于上面的60545。

    实际上浏览器在这里使用了并行连接用来客服单条TCP连接的空载时间以及带宽限制。就像下面一样:

      浏览器会使用并行连接来提升效率,但是需要知道的是,TCP连接本身就会消耗较多的资源。对于一个页面中包含几十上百个HTTP请求的情况,开启几十个TCP连接是不可能的。通常,浏览器会将连接数限制4。本例中,我统计了抓包信息,恰好开启了4个TCP连接。

    连接的关闭

      HTTP基于TCP,TCP又是面向连接的协议。连接有建立就有关闭,我在抓包的时候发现,当所有请求数据都发送完毕的时候,TCP连接并没有马上关闭。

    我们回过头看第一个HTTP请求头信息:

    其中有一项:Connection: keep-alive

    返回头:

    返回头中也有Connection: keep-alive

      在HTTP请求中,keep-alive用来告诉服务器我希望建立一个持久连接,也就是在数据发送完毕后不立即关闭该TCP连接。持久连接能够避免重复地打开关闭连接的消耗同时也能回避TCP慢启动特性带来的损耗。如果服务器同意建立该持久连接,就在响应头中同样包含Connection: keep-alive,否则客户端就会认为服务器不支持keep-alive。本连接是一个持久连接。

      通常持久连接的响应首部还会包含timeout以及max参数,用来估计服务器将连接保持活跃的时长以及保持持久连接数的上限。注意,该值只是估计,不是承诺。不过这里的响应头中并没有包含此类信息。

      本网站我是使用Express框架做的后台,我没有手动设置timeout以及max,也没查到其默认timeout时长,不过我用系统时钟进行了测试,在数据发送完毕后120s左右,TCP连接中断:

    上图中包含了所有4个TCP连接断开的4次挥手信息。

      我发现,在手动关闭网页时也不会立即断开TCP连接。在连接期间刷新网页会继续使用已经建立的TCP连接。但是,如果关闭浏览器,会立即断开TCP连接。

  • 相关阅读:
    web网页测试用例(非常实用)
    怎么做web接口测试
    我的周记13——”离开,是为了更好的回来"
    Lambda 表达式常用函数
    IEnumberable<T>接口
    Linq的学习
    未能加载文件或程序集“Newtonsoft.Json”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。
    拉姆达表达式的笔记
    注册今日头条
    爬取百思不得姐的段子
  • 原文地址:https://www.cnblogs.com/guanghe/p/9216932.html
Copyright © 2020-2023  润新知