一次 HTTP 请求就需要一次 TCP 连接吗?

本文写于 2021 年 2 月 9 日

太长不看版本:短连接需要,长连接不需要。

TCP 的连接与断开

现代浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开呢?

如果会,那什么情况下会断开?

在 HTTP/0.9 版本中,HTTP 请求是以短连接进行的,因此在发送完 HTTP 的响应之后,服务器就会断开 TCP 连接。

可是这样是一件很耗资源、很耗时间的事情,所以在 1.0 版本中,新增了 keep-alive 字段,让长连接被 HTTP 支持了(此时默认还是不会开启长连接)。

所谓长连接,就是完成这个 HTTP 请求之后,不要断开 HTTP 请求使用的 TCP 连接。好处是连接可以被重新使用,之后发送 HTTP 请求的时候就不需要重新建立 TCP 连接了,以及如果维持连接,那么 SSL 的开销也可以避免。

好处如此之多,所以 HTTP/1.1 就把 Connection: keep-alive 头写进了标准,并且默认开启持久连接。

你必须在请求中声明:Connection: close 才会让每次 HTTP 请求都重新建立 TCP 连接。

因此我们有了答案:

  1. 如果是「短连接」,那么一次 TCP 连接就只能对应一次 HTTP 请求;
  2. 如果是「长连接」,那么一次 TCP 连接就可以发送多个 HTTP 请求了。

可以一次性发送多个 HTTP 请求吗?

在 HTTP/1.1 协议中存在一个问题:单个 TCP 连接在一个时刻只能处理一个请求。

也就是说你一个请求处理完了才能处理下一个请求。

这就要看看 Pipelining 了,所谓 pipe 就是管道,而 Pipelining 是 HTTP/1.1 规范中的字段,意为 HTTP 流水线(英语:HTTP pipelining)。

它能将多个 HTTP 请求整批提交,在发送过程中不需先等待服务器的回应。

但唯一的问题在于,这个东西在浏览器中是默认关闭的。

因为该技术存在很多问题:

  • 一些代理服务器不能正确的处理 HTTP Pipelining;
  • 正确的流水线实现是复杂的;
  • Head-of-line Blocking 连接头阻塞:在建立起一个 TCP 连接之后,假设客户端在这个连接连续向服务器发送了几个请求。按照标准,服务器应该按照收到请求的顺序返回结果,假设服务器在处理首个请求时花费了大量时间,那么后面所有的请求都需要等着首个请求结束才能响应。

但是,HTTP2 提供了 Multiplexing 多路传输特性,让我们可以在一个 TCP 连接中同时完成多个 HTTP 请求。

所以,在 HTTP/1.1 时代,浏览器提高页面加载效率的方法主要有下面两种:

  • 维持和服务器已经建立的 TCP 连接,在同一连接上顺序处理多个请求;
  • 和服务器建立多个 TCP 连接。

浏览器对同一 host 的 TCP 连接上限

假设我们还处在 HTTP/1.1 时代,那个时候没有多路传输。

当浏览器拿到一个有几十张图片的网页该怎么办呢?

肯定不能只开一个 TCP 连接顺序下载,那样用户肯定等的很难受。但是如果每个图片都开一个 TCP 连接发 HTTP 请求,那电脑或者服务器都可能受不了——要是有 1000 张图片的话总不能开 1000 个 TCP 连接吧。

所以浏览器允许我们对同一 host 开启多个 TCP 连接,每个浏览器的数量是不一样的。Chrome 最多允许对同一个 Host 建立六个 TCP 连接。

如果图片都是 HTTPS 连接并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器商量能不能用 HTTP2,如果能的话就使用 Multiplexing 功能在这个连接上进行多路传输。

不过也未必会所有挂在这个域名的资源都会使用一个 TCP 连接去获取,但是可以确定的是 Multiplexing 很可能会被用到。

如果发现用不了 HTTP2 呢?或者用不了 HTTPS(现实中的 HTTP2 都是在 HTTPS 上实现的,所以也就是只能使用 HTTP/1.1)呢?

那浏览器就会在一个 HOST 上建立多个 TCP 连接,连接数量的最大限制取决于浏览器设置。这些连接会在空闲的时候被浏览器用来发送新的请求。

如果所有的连接都正在发送请求呢?那其他的请求就只能等等了。

参考:

https://w.cnblogs.com/williamjie/p/11075565.html

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Connection_management_in_HTTP_1.x

https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html

(完)

一次 HTTP 请求就需要一次 TCP 连接吗?的更多相关文章

  1. Http请求的TCP连接

    我们一直认为,HTTP连接分为长连接和短连接,而我们现在常用的都是HTTP1.1,因此我们用的都是长连接. 这句话其实只对了一半,我们现如今的HTTP协议,大部分都是1.1的,因此我们平时用的基本上都 ...

  2. 可能会搞砸你的面试:你知道一个TCP连接上能发起多少个HTTP请求吗?

    本文由原作者松若章原创发布,作者主页:zhihu.com/people/hrsonion/posts,感谢原作者的无私分享. 1.引言 一道经典的面试题是:从 URL 在浏览器被被输入到页面展现的过程 ...

  3. 查看 Apache并发请求数及其TCP连接状态

    查看 Apache并发请求数及其TCP连接状态 (2011-06-27 15:08:36) 服务器上的一些统计数据: 1)统计80端口连接数 netstat -nat|grep -i "80 ...

  4. 查看 并发请求数及其TCP连接状态【转】

    服务器上的一些统计数据: 1)统计80端口连接数netstat -nat|grep -i "80"|wc -l 2)统计httpd协议连接数ps -ef|grep httpd|wc ...

  5. 查看 并发请求数及其TCP连接状态

    服务器上的一些统计数据: 1)统计80端口连接数netstat -nat|grep -i "80"|wc -l 2)统计httpd协议连接数ps -ef|grep httpd|wc ...

  6. 查看 Apache并发请求数及其TCP连接状态【转】

    查看 Apache并发请求数及其TCP连接状态 (2011-06-27 15:08:36) 服务器上的一些统计数据: 1)统计80端口连接数netstat -nat|grep -i "80& ...

  7. 一次http请求,谁会先断开TCP连接?什么情况下客户端先断,什么情况下服务端先断?

    我们有2台内部http服务(nginx): 201:这台服务器部署的服务是account.api.91160.com,这个服务是供前端页面调用: 202:这台服务器部署的服务是hdbs.api.911 ...

  8. “ping”命令的原理就是向对方主机发送UDP数据包,HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”

    Socket  是一套建立在TCP/IP协议上的接口不是一个协议 应用层:  HTTP  FTP  SMTP  Web 传输层:  在两个应用程序之间提供了逻辑而不是物理的通信(TCP  UDP) T ...

  9. TCP 连接与 HTTP 请求的相关问题

    1.现代浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开?什么情况下会断开? 默认情况下建立 TCP 连接不会断开,只有在请求报头中声明 Connection: clo ...

随机推荐

  1. idea中Git的配置和Github上推拉项目

    1.去官网下载Git,并且安装它.安装步骤较为简单,此处就不再赘述. 2.在idea中配置Git信息 Git路径就是你电脑中安装Git的位置,找到git.exe文件(正常情况下,idea都会自动给你匹 ...

  2. 7_线性控制器设计(Linear Controller Design)

    开环系统中 状态方程,其中A的特征值将决定这个系统的表现(稳定性或者收敛速度:特征值小于0时系统稳定) 如果开环系统特征值大于0时(即系统不稳定时): 可以引入输入量U时(U是关于状态变量X的函数), ...

  3. css两栏布局、圣杯布局、双飞翼布局

    最近几个月一直用vue在写手机端的项目,主要写业务逻辑,在js方面投入的时间和精力也比较多.这两天写页面明显感觉css布局方面的知识有不足,所以复习一下布局方法. 两栏布局 1.浮动 .box1 .l ...

  4. 百度开放云 BOS Uploader

    百度开放云 BOS Uploader bce-bos-uploader 是基于 bce-sdk-js 开发的一个 ui 组件,易用性更好.DEMO地址是:http://leeight.github.i ...

  5. 【Android开发】【数据库】LitePal 数据库的使用

    一,导包 dependencies { ...... // LitePal的包 compile 'org.litepal.android:core:1.3.1' ...... } 二,创建bean类 ...

  6. Python IDLE清屏

    在学习和使用Python的过程中,少不了要与Python IDLE打交道.但使用 Python IDLE 都会遇到一个常见而又懊恼的问题--要怎么清屏? 答案是为IDLE增加一个清屏的扩展ClearW ...

  7. SpringBoot2.x修改Redis序列化方式

    添加一个配置类即可: /** * @Author FengZeng * @Date 2022-03-22 13:43 * @Description TODO */ @Configuration pub ...

  8. 时间盲注——AS别名让盲注不盲

    用处 页面存在时间盲注,注入成功了,你啥也看不到. 这只是为了能够查看到注入后的结果 网站部分源代码 <?php $conn = mysqli_("127.0.0.1",&q ...

  9. Leetcode78/90/491之回溯中的子集问题

    回溯之子集问题 子集问题和组合问题特别像 Leetcode78-子集 给你一个整数数组 nums ,数组中的元素 互不相同 .返回该数组所有可能的子集(幂集) 解集 不能 包含重复的子集.你可以按 任 ...

  10. 测试脚本配置、ORM必知必会13条、双下划线查询、一对多外键关系、多对多外键关系、多表查询

    测试脚本配置 ''' 当你只是想测试django中的某一个文件内容 那么你可以不用书写前后端交互的形式而是直接写一个测试脚本即可 脚本代码无论是写在应用下的test.py还是单独开设py文件都可以 ' ...