一次 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. spring DAO 有什么用?

    Spring DAO 使得 JDBC,Hibernate 或 JDO 这样的数据访问技术更容易以一 种统一的方式工作.这使得用户容易在持久性技术之间切换.它还允许您在编写 代码时,无需考虑捕获每种技术 ...

  2. Python - Pycharm常用快捷键

    1. 自动格式调整: pycharm有自动调整代码格式的快捷键,默认为Alt+Ctrl+L 2. 选中相同字符: 快捷键组合:Ctrl + Shift + Alt + J 3.批量缩进: 选择代码区域 ...

  3. 单例模式 | C++ | Singleton模式

    Singleton 模式 单例模式(Singleton Pattern)是 C++/Java等语言中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式实 ...

  4. Vue小说阅读器(仿追书神器)

    一个vue阅读器项目,目前已升级到2.0,阅读器支持横向分页并滑动翻页(没有动画,需要动画的可以自己设置,增加transitionDuration即可) 技术栈 vue全家桶+mint-ui gith ...

  5. C# 委托专题

    单播委托:一个委托只指向一个方法: 多播委托:一个委托指向多个方法,形成一个方法链: Main是静态方法,里面只能引用静态方法,而不能引用实例方法: Main可以进行类的实例化,然后引用实例化后的方法 ...

  6. 针对form表单赋值封装

    1 (function ($){ 2 $.fn.extend({ 3 exajax:function(url,opts,convert){ 4 var ajaxParam = { 5 url:url, ...

  7. setTimeout中第一个参数

    永远不要传递字符串作为setTimeout的第一个参数!!!记住第一个参数只允许函数,或者匿名函数!因为传递字符串有陷阱啊!!它就是披着羊皮的eval啊!!而且上下文会变成全局啊!! 第一个参数为可执 ...

  8. 递归函数求n!

    #include<iostream> using namespace std; int main() { int n; cin>>n; int jieceng(int); co ...

  9. springboot集成spring security实现登录和注销

    文章目录 一.导入坐标 二.Users实体类及其数据库表的创建 三.controller,service,mapper层的实现 四.核心–编写配置文件 五.页面的实现 运行结果 一.导入坐标 < ...

  10. shiro之第一个程序认证

    有关shiro的介绍请访问https://blog.csdn.net/Kevinnsm/article/details/111823268 三个核心组件:Subject, SecurityManage ...