理清 HTTP 之下的 TCP 流程,让你的 HTTP 水平更上一层

430018538f9fab22c9d6825698f7b8c7.gif

作者 | 神说要有光

来源 | 神光的编程秘籍

大家都知道 HTTP 的底层是 TCP,但是可能仅限于知道,并不是真正理解它们的关系。

平时我们用 chrome devtools 的 Network 工具也只是能分析 HTTP 请求:

1acad8da2abb467e4869ca4165a13a00.jpeg

TCP 层的东西看不见摸不着的,所以对它的理解也模模糊糊。

那怎么能看到 TCP 层的数据包来理清 TCP 和 HTTP 的关系呢?

这里推荐一个抓包工具 WireShark,它能抓取 TCP 层的包。

今天我们就用它来抓包分析下 TCP 和 HTTP 吧!

首先,我们准备这样一段服务端代码:

const express = require('express')const app = express()app.get('/', function (req, res) {res.setHeader('Connection', 'close')res.end('hello world');
})app.listen(4000)

用 express 起了一个服务,监听 4000 端口,处理路径为 / 的 get 请求,返回 hello world 的响应体,并设置 Connection: close 的 header。

浏览器访问下:

87ffc47ce0fa47e9451a473e0f42b797.png

header 和 body 都符合预期。

那 TCP 层都做了什么呢?

我们用 WireShark 抓包分析下:

打开 WireShark 后会看到有个设置按钮。

因为我们访问的是 localhost: 4000,所以这里选择本地回环地址那个虚拟网卡,并输入抓包过滤条件为 port 4000:

4617f183206f20d6f98a31a568d2cf17.png

点击 start 开始录制,然后刷新一下浏览器:

这样就能看到抓到的 TCP 数据包:

c9f9f0c6c0b13685c1630ec636b2b9de.jpeg

我们一一分析下。

在分析之前需要了解一些 TCP 基础知识:

TCP 的头部是这样的:

632db5e20a1cf460bcce8b3e9651e5ae.jpeg

TCP 是从端口到端口的传输协议,所以开始是源端口和目的端口。

接下来是序列号(sequence number),表示当前包的序号,后面是确认的序列号(acknowledgment number),表示我收到了序号为 xxx 的包。

然后红框标出的部分是 flags 标识位,通过 0、1 表示有没有:

这里我们只会用到其中的 SYN、ACK、FIN:

  • SYN:请求建立一个连接(说明这是链接的开始)

  • ACK:表示 ack number 是否是有效的

  • FIN:表示本端要断开链接了(说明这是链接的结束)

有了这些,我们就知道怎么区分 TCP 链接的开始和结束了。

再看一下抓到的包:

53324b1396bf78cafc494aed54408d29.jpeg

有 SYN 标志位的是连接的开始,有 FIN 标志位的是连接的结束,所以我们分为 3 段来看:

首先是连接开始的部分:

2cf93fd9c7f1b6d3660b8c58d83b9b94.png

大家听过 TCP 的三次握手么?说的就是这个。

其中有一个端口是 4000,这个是服务的端口,那另一个端口 57454 明显就是浏览器的端口。

首先是浏览器向服务器发送了一个 SYN 的 TCP 请求,表示希望建立连接,序列号 Seq 是 0。

严格来说,序列号的相对值是 0,绝对值是 2454579144。

16906c867bb1e6dc8040adf676a15c89.png

然后服务器向浏览器发送了一个 SYN 的 TCP 请求,表示希望建立连接,ACK 是 1,代表现在的 ack number 是有效的:

ca786e34f468d11ff678a738570c73cf.png

这里 ack number 的相对值是 1,绝对值是 2454579145,不就是上个 TCP 数据包的 seq 加 1 么?

TCP 连接中就是通过返回 seq number + 1 作为 ack number 来确认收到的。

然后又返回了一个 seq number 给浏览器,相对值是 0, 绝对值是 2765691269。

浏览器收到后返回了一个 TCP 数据包给服务器,ack number 自然是 2765691270,代表收到了连接请求。

这样浏览器和服务器各自向对方发送了 SYN 的建立连接请求,并且都收到了对方的确认,那么 TCP 连接就建立成功了。

这就是 TCP 三次握手的原理!

eb6957c645cb029709598c326ebf4dce.png

趁热打铁来看下四次挥手的部分:

e7dfbe91b29bd908291a0f6e8857dc23.png

浏览器向服务器发送了有 FIN 标志位的数据包,表示要断开连接,然后服务端返回了 ACK 的包表示确认。

之后服务端发送了 FIN 标志位的数据包给浏览器,表示要断开连接,浏览器也返回了 ACK 的包表示确认。

这样就完成了四次挥手的过程。

当然,具体确认的还是靠 ack number = seq number + 1 来实现的,和上面的一样,就不展开了:

53679f101b97aca5079addfe6d348a1f.png60cb315e4530e7112a2c167064596f12.png

我们通过抓包理清了 TCP 连接建立和连接的过程。

4daf7ac4176f1b7375e1cbdc1b0c98fb.png

那么为什么握手是三次,挥手是四次呢?

因为挥手是一个 FIN,一个 ACK,一个 FIN + ACK,一个 ACK:

3e2f7eed696bdffae638f44139d29c66.png

而握手是一个 SYN,一个 ACK + SYN,一个 ACK:

9f6b8ecc83a81ab8a99503e1070ed2f6.png

不过是因为握手时把 ACK 和 SYN 合并到一个数据包了而已。

那挥手时能合并成三次么?

不能!因为有两个 ack number,怎么合并,冲突了,而握手时只有一个 ack number,自然可以合并。

bdee5f4f8899f881a4041cbfcc03accd.png

接下来再来看下连接建立后的 http 请求和响应吧:

3e92f034c981b89f4bcadd8a47432e81.png

其实一次 HTTP 请求响应会有四个 TCP 数据包,其中两个数据包与滑动窗口有关,这里先不展开了。

相对值是 ack number = seq number + 1 没错,但是绝对值不是:

绝对值 2454579855 = 2454579145 + 710,也就是 ack number = seq number + segment len。

这些细节暂时不用深究。

总之,我们知道了HTTP 的请求和响应是通过序列号关联在一起的。

就算同一个 TCP 链接并行发送多个 HTTP 的请求和响应,它们也能找到各自对应的那个。就是通过这个 seq number 和 ack number。

这里为啥链接建立了发送了一个请求就断掉了呢?

我刷新浏览器,请求了两次,发现经历了两次连接的建立、http 请求响应、连接断开:

3788ebfbf816f08158de3a85b0b8be13.png

这是因为我设置了 Connection:close 的 header,它的作用就是一次 http 请求响应结束就断开 TCP 链接。

48b55447a4770e839e01eb61eb49c69f.png

我们改成 HTTP 1.1 支持的 keep-alive 试试:

f40e2306d518af6abf2f19bbe6e1ee64.png

设置 Connection 为 keep-alive,然后设置 keep-alive 的细节为 timeout 10 ,也就是 10s 后断开。

重启服务器,再刷新下浏览器试试:

0a27c4e7ff170a6d6871af79fc9a4951.png

可以看到在一个 TCP 连接内发送了多次 http 请求响应。(通过 SYN 开始,FIN 结束)

这就是 keep-alive 的作用。

细心的同学会发现只是浏览器向服务器发送了 FIN 数据包,服务器没有发给浏览器 FIN 数据包。

这是因为 keep-alive 的 header 只是控制的浏览器的断开连接的行为,服务器的断开连接逻辑是独立的。

这样,我们就理清了 HTTP 在 TCP 层面的流程,连接的建立、断开,请求响应,还有 keep-alive。

总结

我们平时都是分析 HTTP 请求响应,TCP 对我们来说看不见摸不着的,理解的模模糊糊。

所以今天我们用 WireShark 抓了下 TCP 的包,来理清了 TCP 和 HTTP 的关系。

TCP 是从一个端口到另一个端口的传输控制协议,TCP header 中有序列号 seq number、确认序列号 ack number,还有几个标志位:

  • SYN 标志位代表请求建立连接

  • ACK 标志位代表当前确认序列号是有效的。

  • FIN 标志位代表请求断开连接

然后我们抓了 localhost:4000 的包分析了下 HTTP 请求的 TCP 流程,理清了三次握手(SYN、SYN + ACK、ACK),四次挥手(FIN、ACK、FIN + ACK、ACK)的连接建立、断开的流程。知道了为什么不能三次挥手(因为两个 ACK 冲突了)

然后还理清了同一个 TCP 连接传输的多个 HTTP 请求响应是通过 seq number 和 ack number 来关联的。

之后我们分别测试了 Connection:close 和 Connection:keep-alive 的情况,发现确实 keep-alive 能减少频繁的连接建立和断开,能复用同一个 TCP 链接。

HTTP 是通过 TCP 完成端口到端口的数据传输的。一个 TCP 连接可以传输多个 HTTP 请求、响应。请求和响应的关联是通过 TCP 包的序列号 seq。

理清了 TCP 和 HTTP 的关系,你是否对 HTTP 的理解更深了呢?

a8489fbc7763d7d66c9bb2b23f8276cb.gif

往期推荐

40 张图 详解 Docker 容器监控

剖析 kubernetes 集群内部 DNS 解析原理

Docker 镜像和容器的导入导出及常用命令

如何从 Docker 镜像里提取 dockerfile!

fd2a070797d61f135a26d756d728f77e.gif

点分享

f3404246ccc307d4e374a9e3ea57192f.gif

点收藏

d240af79976cf1a337f2520e00533f87.gif

点点赞

4dc69b60eae19b7e4392cd91f81e8714.gif

点在看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/511225.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于 EventBridge 构建 SaaS 应用集成方案

简介:事件源是事件驱动的基石,如何获取更多事件源也是 EventBridge 一直在探索和尝试的方向。针对市场上其他云厂商和垂直领域的 Saas 服务,EventBridge 发布了 HTTP Source 能力,提供简单且易于集成的三方事件推送 ,帮…

无缝融入 Kubernetes 生态 | 云原生网关支持 Ingress 资源

简介:Kubernetes 一贯的作风是通过定义标准来解决同一类问题,在解决集群对外流量管理的问题也不例外。Kubernetes 对集群入口点进行了进一步的统一抽象,提出了 3 种解决方案:NodePort、LoadBalancer 和 Ingress。 作者&#xff1…

阿里云 AI 编辑部获 CCBN 创新奖,传媒行业解决方案背后的黑科技

简介:视频云驱动智媒创新 5 月 27 日,CCBN(第二十八届中国国际广播电视信息网络展览会)在北京隆重召开,在本次的 “CCBN 年度创新奖” 评选中,阿里云视频云凭借 AI 编辑部的传媒行业专业解决方案获得 CCBN …

云原生正在吞噬一切,开发者该如何应对?

十年前,Netscape创始人、硅谷著名投资人马克安德森(Marc Andreessen)预言“软件正在吞噬世界”;数年后,软件里90%以上的代码都是开源代码,“开源正在吞噬软件”;如今,“云原生吞噬开…

阿里云视频云 Retina 多媒体 AI 体验馆开张啦

简介:带你体验视频更多可能 带你体验视频更多可能 海量视频管理难度大?翻库检索特定人物费时费力?视频内容剪辑效率低?您的得力助手“Retina多媒体AI”体验馆已上线。带你感受视频AI黑科技,开启极致智能体验。 1、智…

一篇文章了解 Docker 的安装、启动以及工作原理!

作者 | 是泡泡来源 | CSDN博客Docker 浅谈1.1 Docker 为什么出现我们知道,传统的项目开发和运维是两套环境,而且要一一配置环境并且有的时候更新还会导致服务不可用,这就很麻烦了,那么有没有一种很方便不用这么麻烦的技术可以一键…

技术解读:英特尔 x86 平台上,AI 能力是如何进行演进的?(附PPT)

简介:AI 生态系统是怎样的?其中又有哪些关键技术? AI 计算力的指数增长意味着,为了解决越来越复杂的用例,即使是 1000 倍的计算性能增长也很容易被消耗。因此,需要通过软件生态系统的助力,才能…

Apsara Stack 技术百科 | 浅谈阿里云混合云新一代运维平台演进与实践

简介:随着企业业务规模扩大和复杂化及云计算、大数据等技术的不断发展,大量传统企业希望用上云来加速其数字化转型,以获得虚拟化、软件化、服务化、平台化的红利。在这个过程中,因为软件资产规模持续增大而导致的软件开发运维和IT…

Java应用结构规范

简介:在Java程序开发中,命名和应用分层无疑是广大后端同胞的两大“痛点”,本文提供一种基于领域模型的轻量级应用分层结构设计,供大家参考。下面按分层结构、分层明细、调用关系、各层规范和通用代码工具展开介绍。 作者 | 阿卓 来…

Gartner:2022年全球半导体收入增长预计将放缓至7%,远低于2021年26.3%

2022年来自个人电脑的半导体收入将下降5.4% 供稿 | Gartner 出品 | CSDN云计算 根据Gartner的最新预测,2022年全球半导体收入预计将增长7.4%,相比上一季度预测的13.6%有所下降并且远低于2021年的26.3%。 Gartner研究业务副总裁Richard Gordon表示&#…

Linux 中的管道是什么?管道重定向是如何工作的?

作者 | 刘光录来源 | TIAP我们在命令行中经常会用到类似 cmd0 | cmd1 | cmd2 的写法。其实,这是管道重定向(pipe redirection),用于将一个命令的输出作为输入重定向到下一个命令。那么,你知道它具体是怎么工作的吗&…

AliRTC 开启视频互动 “零计算” 时代

简介:在 2021 云栖大会《产业视频化创新与最佳实践》视频云主题论坛中,阿里云智能高级技术专家在《AliRTC 开启视频互动 "零处理" 时代》的主题演讲中,发布了阿里云视频云下一代实时交互解决方案 —RTC “零处理”,同时…

网易数帆Curve加入PolarDB开源数据库社区

简介:Curve社区签署阿里巴巴开源CLA(Contribution License Agreement, 贡献许可协议), 正式与阿里云PolarDB 开源数据库社区牵手。 Curve社区签署阿里巴巴开源CLA(Contribution License Agreement, 贡献许可协议), 正式与阿里云PolarDB 开源数据库社区牵手。 Polar…

新起之秀 DPU,正在掀起数据中心变革!

在全产业数字化转型趋势之下,网络数据呈海量增长态势,传统 CPU 解决方案已无法负载现有的业务量——数据处理的效能受到限制;上层的应用计算能力受到限制。此时,DPU 逢时而生,DPU能够通过对网络、储存、算力等资源的有…

阿里云数据库开源发布:PolarDB三节点高可用的功能特性和关键技术

简介:在3月2日的阿里云开源 PolarDB 企业级架构发布会上,阿里云数据库技术专家孟勃荣 带来了主题为《PolarDB 三节点高可用》的精彩演讲。三节点高可用功能主要为 PolarDB 提供金融级强一致性、高可靠性的跨机房复制能力,基于分布式共识算法同…

全员学习低代码,一汽大众领跑数智化转型背后的秘密

简介:500位低代码开发者,90%来自一线,低代码开发在一汽-大众百花齐放。 一汽-大众有500位低代码开发者,90%是来自一线的业务人员,他们如何用低代码解决身边的数字化需求?钉钉宜搭《102个开发者故事》走进一…

智领云CEO彭锋:DataOps,大数据的新战线

作者 | 彭锋 供稿 | 智领云 2008年我在我的第一份工作(Ask.com)中开始使用Hadoop。当时是因为昂贵的Oracle集群无法处理不断增加的分析工作量,公司不得不切换到Hadoop。随后在Twitter担任数据工程师的第二份工作中,我在第一线参…

宜搭小技巧|维护Excel太麻烦?Excel一键转应用,为你的工作减负

简介:只需6步,轻松学会「Excel一键创建应用」! 在钉钉的聊天窗口中,每天都会流转数量巨大的Excel表格,用于信息收集和数据统计,但有时这些表格并不能很好地帮助到我们的工作,相反还会带来许多不…

阿里云发布第四代神龙架构,提供业界首个大规模弹性RDMA加速能力

简介:10月20日,2021年杭州云栖大会上,阿里云发布第四代神龙架构,升级至全新的eRMDA网络架构,是业界首个大规模弹性RDMA加速能力。 10月20日,2021年杭州云栖大会上,阿里云发布第四代神龙架构。相…

性能提升40%,阿里云神龙大数据加速引擎获TPCx-BB世界排名第一

简介:神龙大数据加速引擎,针对大数据常用组件,如Spark、Hadoop、Alluxio等,结合阿里云神龙架构的特性,进行软硬一体化优化,形成独一无二的性能优势,最终,使复杂SQL查询场景性能相比社区版spark提…