一次 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 应用程序有哪些不同组件?

    Spring 应用一般有以下组件:接口 - 定义功能.Bean 类 - 它包含属性,setter 和 getter 方法,函数等.Spring 面向切面编程(AOP) - 提供面向切面编程的功能.Be ...

  2. HTML 5的页面结构和HTML 4或早先的HTML有什么不同?

    一个典型的Web页面有页眉(header),页脚(footer),导航(navigation),正文(central area)和侧栏(side bar).现在如果是在HTML 4中,HTML部分中的 ...

  3. ROS环境变量的设置

    一.前言(大神可以直接跳过) 本博客主要就是为了介绍ROS中环境变量的设置过程,还不是很了解ROS的可以去看一下我的博客,ROS简介-从零开始讲解ROS(适合超零基础阅读) ROS为什么需要设置环境变 ...

  4. 巧用CSS3:target 伪类制作Dropdown下拉菜单(无JS)

    原文链接:http://devework.com/css3-target-dropdown.html :target 是CSS3 中新增的一个伪类,用以匹配当前页面的URI中某个标志符的目标元素(比如 ...

  5. snippet,让你编码效率翻倍

    为什么谈到Snippet 今天下午在用vscode做小程序的时候,发现很不方便,因为商店里提供的代码片段极为有限,而且平时几乎每天都需要用到代码片段,所以就在思考他们是怎么做到给别人提供代码的,我可以 ...

  6. Unity中让Update中的方法执行一次

    Unity中让Update中的方法执行一次 Unity中,很多时候,代码需要放在Update中时刻监测状态,一旦状态符合,又只需要代码执行一次:其实可以通过设置控制量的方式,让代码只执行一次:方法:设 ...

  7. 大数据学习之路又之从csv文件到sql文件的操作过程

    根据前几天的测试,简单的做个总结 csv文件的字段说明: 1.将csv文件上传到虚拟机中 在SecureCRT中点击,创建目录,直接把文件从本地拖拽进去 我放在了/linmob/data的路径下,所以 ...

  8. 【转】shim.ChaincodeStubInterface用法

    作为记录 shim.ChaincodeStubInterface用法

  9. Struts2中将表单数据封装到List和Map集合中

    一.将表单数据封装到Map集合中 1.创建MapAction类 import cn.entity.User; import com.opensymphony.xwork2.ActionSupport; ...

  10. Java对象和多态

    Java对象和多态 (面向对象) 面向对象基础 面向对象程序设计(Object Oriented Programming) 对象基于类创建,类相当于一个模板,对象就是根据模板创建出来的实体(就像做月饼 ...