分布式专题——25 深入理解网络通信和TCP、IP协议
1 计算机网络是什么
1.1 定义与分类
- 定义:利用通信线路将地理上分散、有独立功能的计算机系统和通信设备按不同形式连接,依靠完善的网络软件和协议,实现资源共享与信息传递的系统;
- 分类:
- 按覆盖范围分,有局域网(LAN,作用范围一般几米到几十公里)、城域网(MAN,介于LAN和WAN之间)、广域网(WAN,作用范围一般几十到几千公里);
- 还可按拓扑结构(总线型、环型、星型、网状)、按信息交换方式(电路交换、报文交换、报文分组交换)等方式分类。
1.2 发展简史
-
诞生阶段:20世纪60年代中期之前,是第一代以单个计算机为中心的远程联机系统;
-
ARPANET(阿帕网):20世纪60年代初,美国国防部为构建分散指挥系统,资助建立ARPANET,将多所大学计算机主机联接,采用分组交换技术,E - mail、FTP和Telnet在此网络诞生;
-
开放性标准化体系结构:ARPANET兴起后,因不同厂商产品互联困难,需要统一标准,ISO和IEEE相继提出OSI参考模型和TCP/IP模型,最终TCP/IP模型因协议可行性强、能应对技术革新且及时改良,成为事实上的标准;
-
Internet互联网:20世纪90年代至今的第四代计算机网络,即我们熟知的互联网;
-
网络协议的作用:不同公司、不同体系结构的计算设备(如电脑、手机)要在网络中通信,就像不同方言区的人需要普通话来沟通一样,网络协议起到了让计算机之间能够顺利沟通的作用。要成为计算机网络领域高手,理解网络协议的构成、原理和工作方式是学习该领域知识的关键过程。
2 计算机网络体系结构
2.1 OSI 七层模型
-
开放系统互连参考模型(Open System Interconnect,简称 OSI),由国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定,为开放式互连信息系统提供功能结构框架,目的是为异种计算机互连提供共同基础和标准框架,保持相关标准的一致性与兼容性。这里的开放系统指遵循 OSI 参考模型和相关协议能实现互连、有各种应用目的的计算机系统;
-
OSI 模型采用分层的结构化技术,共分七层,从下到上依次是:
- 应用层:为应用程序提供服务
- 表示层:进行数据格式转化、数据加密
- 会话层:建立、管理和维护会话
- 传输层:建立、管理和维护端到端的连接
- 网络层:负责 IP 选址及路由选择
- 数据链路层:提供介质访问和链路管理
- 物理层:涉及物理层面的相关内容
2.2 TCP/IP 模型
-
OSI 模型复杂且学术化,实际使用的 TCP/IP 模型分 5 层,包括物理层、数据链路层(也有将物理层和数据链路层合称为网络接口层,对应 TCP/IP 四层协议模型)、网络层、传输层、应用层;
-
与 OSI 模型的对应关系:
- OSI 模型的应用层、表示层、会话层对应 TCP/IP 模型的应用层;
- OSI 模型的传输层对应 TCP/IP 模型的传输层;
- OSI 模型的网络层对应 TCP/IP 模型的网络层;
- OSI 模型的数据链路层对应 TCP/IP 模型的数据链路层;
- OSI 模型的物理层对应 TCP/IP 模型的物理层;
-
每一个抽象层建立在低一层提供的服务上,并为高一层提供服务。对于 PC 机,物理层可看成网卡,数据链路层可看成网卡驱动程序,网络层和传输层由操作系统负责处理,应用层则是常用的网络应用程序和自己编写的网络应用程序。
2.3 TCP/IP 协议族
-
Transmission Control Protocol/Internet Protocol(传输控制协议/因特网互联协议),是 Internet 最基本的协议、国际互联网络的基础,由网络层的 IP 协议和传输层的 TCP 协议组成,采用 5 层的层级结构,是利用 IP 进行通信时必须用到的协议群的统称,是由多个不同层协议组成的协议家族,是互联网的基础通信架构;
-
与 OSI 模型的对应及各层协议:
- 应用层:包含 HTTP、Telnet、FTP、TFTP、DNS、SMTP 等协议;
- 传输层:包含 TCP、UDP 协议;
- 网络层:包含 IP、ICMP、RIP、IGMP 等协议;
- 数据链路层:包含 ARP、RARP、IEEE802.3、PPP、CSMA/CD 等协议;
- 物理层:包含 FE 自协商、Manchester、MLT - 3、4A、PAM5 等;
-
IP、TCP 和 UDP
- IP:网际协议,是 TCP/IP 中非常重要的协议,用来确定网络中唯一的一台计算设备,作用类似现实生活中的电话号码或通讯地址,负责对数据加上 IP 地址(源地址和目的地址)和其他数据以确定传输目标;
- TCP 和 UDP:都是传输层的协议,传输层主要为两台主机上的应用程序提供端到端的通信;
- TCP:提供可靠的数据传输服务,面向连接。通信的两台主机首先要建立连接,连接建立后才开始传输数据,传输过程中采用“带重传的肯定确认”技术保证可靠性,还采用“滑动窗口”方式进行流量控制,发送完成后会关闭连接,类似日常生活中打电话,有确认身份、重说、控制语速、结束通话等可靠的交互过程;
- UDP:中文名是用户数据报协议,是不可靠的传输,把数据直接发出去,不管对方是否接收、能否接收,也不需要接收方确认,可能会出现丢包现象,实际应用中要求程序员编程验证,类似通过不靠谱的物流系统寄东西。所以 TCP 比 UDP 可靠得多;
-
注意事项:一些常见的网络应用基于 TCP 和 UDP,这两个协议会使用网络层的 IP 协议,但也可以绕过传输层的 TCP 和 UDP 直接使用 IP,比如 Linux 内核中的 LVS 可直接基于 IP 层进行负载平衡调度;甚至还可以直接访问链路层,比如 tcpdump 程序直接和链路层进行通信。
2.4 TCP/IP 网络传输中的数据
-
数据传输的基本原理:
-
在 TCP/IP 网络模型的每个分层中,都会对发送的数据附加一个首部,首部包含该层必要信息(如目标地址、协议相关信息等);
-
协议提供的信息为包首部,要发送的内容为数据,且下一层会把上一层收到的包全部当作本层的数据;
包指的就是数据包;
-
网络中传输的数据包由协议首部和上一层传来的数据两部分组成,首部结构由协议具体规范定义,能标明协议读取数据的方式,也能体现协议必要信息和要处理的数据;
-
-
发送端(用户 A)的数据处理流程
- 应用程序处理:应用程序先进行编码处理,生成报文/消息(message),然后交给下面的 TCP 层;
- TCP 模块处理:TCP 依据应用的指示,负责建立连接、发送数据和断开连接,为应用层数据提供可靠传输到对端的服务。为此,TCP 会将应用层数据封装为报文段(segment),并附加 TCP 首部,之后交给 IP 层;
- IP 模块处理:IP 把 TCP 传过来的 TCP 首部和 TCP 数据合起来当作自己的数据,在 TCP 首部前端加上 IP 首部,生成 IP 数据报(datagram),再交给数据链路层;
- 数据链路层处理:对数据链路层而言,从 IP 传过来的 IP 包就是数据。数据链路层会给这些数据附加链路层首部,封装为链路层帧(frame),生成的链路层帧通过物理层传输给接收端(用户 B);
-
接收端(用户 B)的数据处理流程
- 数据链路层处理:用户 B 主机收到链路层帧后,先从链路层帧首部找 MAC 地址,判断是否是发给自己的包,若不是就丢弃数据;若是发给自己的包,就从以太网包首部的类型确定数据类型,再传给相应模块(如 IP、ARP 等,此处例子为 IP);
- IP 模块处理:IP 模块接收数据后,从包首部判断 IP 地址是否与自己的 IP 地址匹配,若匹配,就根据首部的协议类型将数据发送给对应的模块(如 TCP、UDP 等,此处例子为 TCP);
- TCP 模块处理:在 TCP 模块中,首先计算校验和,判断数据是否被破坏;接着检查是否按序号接收数据;最后检查端口号,确定具体的应用程序。数据被完整接收后,会传给由端口号识别的应用程序;
- 应用程序处理:接收端应用程序直接接收发送端发送的数据,通过解析数据,展示相应内容;
2.5 地址和端口号
2.5.1 MAC 地址
-
媒体访问控制(Media Access Control)地址,也叫局域网地址(LAN Address)、MAC 位址、以太网地址(Ethernet Address)或物理地址(Physical Address),由网络设备制造商生产时写在硬件内部(如网卡的 BIOS 里);
-
MAC 地址与网络无关,带有该地址的硬件(如网卡、集线器、路由器等)接入网络任何位置,MAC 地址都相同,理论上除非盗来硬件,否则无法冒名顶替;
-
MAC 地址共 48 位(6 个字节),前 24 位由 IEEE(电气和电子工程师协会)决定分配方式,后 24 位由生产网络设备的厂商自行制定,例如
FF:FF:FF:FF:FF:FF
或FF-FF-FF-FF-FF-FF
; -
查看方式:
-
Windows 系统下,可用
ipconfig -all
命令查看; -
Linux 系统下,常用的有 4 种方式:
ifconfig -a ip link show cat /sys/class/net/eth0/address # 查看 eth0 的 MAC 地址 dmesg | grep eth0
在Linux系统中,
eth0
是网络接口的一种命名标识;在传统的网络接口命名方式中,
eth
是Ethernet(以太网)的缩写,表示这是一个以太网接口。后面的数字是接口的编号,从0开始,eth0
就是系统识别到的第一个以太网接口 。比如,如果计算机装有多个以太网网卡,可能还会有eth1
、eth2
等;
-
2.5.2 IP 地址
-
IP 地址(Internet Protocol)全称互联网协议地址,为互联网上每个网络和每台主机配置唯一的逻辑地址,用于与物理地址区分;
-
IP 地址用来识别 TCP/IP 网络中互连的主机和路由器。IP 地址基于逻辑,灵活且不受硬件限制,容易记忆;
-
分为 IPv4 和 IPv6(前者是重点)。IPv4 地址由 32 位二进制数组成,通常分为 4 个“8 位二进制数”(即 4 个字节),格式为(A.B.C.D),其中 A、B、C、D 为 0 - 255 的十进制整数,例如 192.168.1.1;
-
IP 地址和 MAC 地址的区别
- 可更改性:IP 地址只要不重复,可根据网络拓扑随意更改;MAC 地址由生产厂商烧录,一般不能改动,只有当 PC 机网卡损坏更换后,MAC 地址才会改变;
- 长度:IP 地址长度为 32 位,MAC 地址为 48 位;
- 寻址协议层:IP 地址应用于 OSI 模型的网络层,MAC 地址应用于 OSI 模型的数据链路层。数据链路层协议通过 MAC 地址使数据在相同链路的节点间传递,网络层协议借助 ARP 根据目的 IP 地址找到中间节点 MAC 地址,通过中间节点传送,使数据在不同网络间传递;
- 分配依据:IP 地址分配基于自身定义的网络拓扑,MAC 地址分配基于制造商。
2.5.3 端口号
-
端口号的定义与作用
- 传输层有类似地址的概念即端口号,它用于识别同一台计算机中进行通信的不同应用程序,也被称为程序地址;
- 一台计算机可同时运行多个程序,传输层协议利用端口号识别本机中正在通信的应用程序,从而准确传输数据;
-
端口号的数量:因为 TCP、UDP 协议报文开头,分别用 16 位二进制存储源端口号和目标端口号,所以端口总数是 216=655362^{16}=65536216=65536 个。但 0 号端口表示所有端口,实际可用端口号为 65535 个;
-
端口号的确定方式
- 标准既定的端口号(静态法):每个应用程序有指定端口号,并非可随意使用。像 HTTP、FTP、TELNET 等广泛使用的应用协议,使用的是固定端口号,这些知名端口号分布在 0~1023 之间,编写网络应用服务时尽量不使用;
- 时序分配法:服务器需确定监听端口号供客户端访问服务,而客户端无需确定端口号。客户端应用程序可全权交给操作系统分配临时端口号,操作系统分配的一般大于 10000;
-
端口号的查看方法
- Windows 系统:
- 使用
netstat -ano
查看所有端口号; - 使用
netstat -ano|findstr "<端口号>"
查看指定端口号;
- 使用
- Linux 系统:
- 用 root 用户执行
lsof -i:端口号
查看指定端口占用,例如lsof -i:3306
可查看 3306 端口占用情况; lsof -i -U
可显示所有打开的 UNIX domain 和端口文件;- 更多使用的事
netstat
命令:netstat -tunlp
用于显示 TCP、UDP 的端口和进程等相关情况;netstat -tunlp | grep 端口号
可查看指定端口占用。其中,-t
仅显示 TCP 相关选项,-u
仅显示 UDP 相关选项,-n
拒绝显示别名,能显示数字的全部转化为数字,-l
仅列出处于监听(Listen)状态的服务,-p
显示建立相关链接的程序名。
- 用 root 用户执行
- Windows 系统:
2.6 网络通信的标识元素
-
一般而言,计算机的每个网卡都有固定不变的 MAC 地址,正常工作的网卡会有可变化的 IP 地址,计算机中的应用程序可拥有自己的端口号,通过服务器网卡进行网络通信;
-
一台服务器上不同网络应用程序必须使用不同端口号,若程序 A 用了端口 x,程序 B 再用会报错“Address already in use”;
-
操作系统通过源 IP 地址、目标 IP 地址、协议号(协议类型)、源端口号以及目标端口号这五个元素,唯一性识别网络上的通信;
-
面试题:一台主机上只能保持最多 65535 个 TCP 连接,对吗?
以下的讲解都基于服务器和客户端都只有 1 个 IP 地址;
-
不对,下面从服务端和客户端两个角度展开分析;
-
服务端
- TCP 连接由源 IP 地址、源端口、目的 IP 地址和目的端口构成四元组,四元组中任意一个元素改变,就代表一条新连接。以 MySQL 为例:
- 用户 A 基于 IP 地址 A1、端口 PA 连接 MySQL(IP 为 X,端口 3306),构成四元组 (A1, PA, X, 3306);
- 用户 B 基于 IP 地址 B1、端口 PB 连接同一 MySQL,构成新四元组 (B1, PB, X, 3306),MySQL 无需开启新端口;
- 服务端理论上能达成的最高并发数量:目的 IP 地址和目的端口(X, 3306)不变时,源 IP 地址最大有 2322^{32}232 个,端口数量有 2162^{16}216 个,两者相乘约两百多万亿,所以理论上每个服务器可接收的连接上限约为两百多万亿。但实际上做不到,工程实践中连接数在千万级别,基于 Java 的应用程序大概能支持百万级别;
- TCP 连接由源 IP 地址、源端口、目的 IP 地址和目的端口构成四元组,四元组中任意一个元素改变,就代表一条新连接。以 MySQL 为例:
-
客户端
- 客户端应用程序可不用自己设置端口号,由操作系统分配。虽然可用端口号约 6 万多,但从 TCP 连接四元组(源 IP 地址、源端口、目的 IP 地址、目的端口)考虑,只要服务器的 IP 或端口不一样,即使客户端的 IP 和端口相同,也是不同连接。例如客户端 IP 10000 分别连接服务器 IP 10000 和 20000,是两条不同连接,且客户端同一个端口可以连接不同服务器;
- 客户端启动时不显示绑定到某个端口上,内核可使用一个端口连接不同服务端,且不会产生数据混乱,因为源 IP 地址、目标 IP 地址、源端口号以及目标端口号能唯一性确定一个 TCP 连接。由于四元组里有 3 个元素可变,所以客户端能同时支持的连接数比服务器大得多。
-
3 TCP 特性
3.1 概述
- 连接特性:TCP 是面向连接的通信协议,通过三次握手建立连接后,才能开始数据的读写,通讯完成时要拆除连接,且只能用于端到端的通讯;
- 可靠传输:提供可靠的数据流服务,数据可能被拆分发送,超时重传机制和应答确认机制是其可靠传输的关键设计;
- 超时重传机制:核心是重传超时(RTO,Retransmission TimeOut)时间的选择。由于网络环境复杂多变,固定超时时间不经济且不准确,需根据网络情况动态调整。通过采样统计数据包从发送端到接收端再到收到回复的时长(RTT,round - trip time),经算法平滑 RTT 值后,确定重传超时值;
- 数据包处理:
- IP 层传输数据不能保证数据包按发送顺序到达目的机器,当 IP 层将数据传至 TCP 层后,TCP 会对数据包进行排序和错误检查;
- TCP 数据包包含序号和确认信息,可对未按序收到的包排序,对损坏的包重传;
- 流量控制:采用“滑动窗口”方式进行流量控制,窗口表示接收能力,用于限制发送方的发送速度;
- 全双工通信:允许在一个 TCP 连接上,通信双方同时传输数据;
- 应用场景:
- 面向连接且需要高度可靠性的服务(如 Telnet、FTP、rlogin、X Windows 和 SMTP)使用 TCP;
- DNS 在发送和接收域名数据库时使用 TCP,传送有关单个主机的信息时使用 UDP。
3.2 TCP 三次握手
3.2.1 过程
-
TCP 提供面向有连接的通信传输,面向有连接是指在数据通信开始前做好两端的准备工作。三次握手是建立 TCP 连接时,客户端和服务器端总共发送三个包以确认连接建立,在 socket 编程中由客户端执行
connect
触发,发起连接的一方为客户端,接收连接的一方为服务端; -
简易速记版:
-
详细细节版:
-
第一次握手:客户端将请求报文标志位 SYN 置为 1,在请求报文的 Sequence Number 字段(简称 seq)中填入随机值 J,发送数据包给服务器端,客户端进入 SYN_SENT 状态,等待服务器端确认;
-
第二次握手:服务器端收到数据包后,由请求报文标志位 SYN = 1 知道客户端请求建立连接,将应答报文标志位 SYN 和 ACK 都置为 1,在应答报文的 Acknowledgment Number 字段(简称 ack)中填入 ack = J + 1,在应答报文的 seq 中填入随机值 K,发送数据包给客户端以确认连接请求,服务器端进入 SYN_RCVD 状态;
-
第三次握手:
- 客户端收到应答报文后,检查 ack 是否为 J + 1,ACK 是否为 1,若正确则将第三个报文标志位 ACK 置为 1,ack = K + 1,发送数据包给服务器端;
- 服务器端检查 ack 是否为 K + 1,ACK 是否为 1,若正确则连接建立成功,客户端和服务器端进入 ESTABLISHED 状态,之后可开始传输数据。
3.2.2 TCP 握手需要三次的原因
- TCP 是可靠的传输控制协议,三次握手是保证数据可靠传输又能提高传输效率的最小次数;
- 为实现可靠数据传输,TCP 协议的通信双方都必须维护一个序列号,以标识发送出去的数据包中哪些已被对方收到;
- 例如发送方发送大小为 10 byte、序号为 500 的数据包,接收方收到后回复确认号 510(500 + 10),告知发送方可以发送下一个序号从 511 开始的数据包;
- 三次握手的过程是通信双方相互告知序列号起始值,并确认对方已收到序列号起始值的必经步骤;
- 若只有两次握手,至多只有连接发起方的起始序列号能被确认,另一方选择的序列号则得不到确认;
- 而三次握手后,通信双方都已知道对方序列号起始值,也确认了对方知道自己的序列号起始值,第四次握手无必要。
3.2.3 漏洞:SYN 洪泛攻击及解决方案
- SYN 洪泛攻击:
- 在 TCP 三次握手中,第二次握手时服务端向客户端应答请求需要客户端 IP,且握手未完成时操作系统用队列维持该状态(Linux 2.2 以后,队列大小可通过
/proc/sys/net/ipv4/tcp_max_syn_backlog
设置); - 攻击者伪造客户端 IP,向服务端狂发第一次握手内容,服务端忙于进行第二次握手,但因客户端 IP 是伪造的,第二次握手无应答,导致服务器队列满,拒绝连接;
- 在 TCP 三次握手中,第二次握手时服务端向客户端应答请求需要客户端 IP,且握手未完成时操作系统用队列维持该状态(Linux 2.2 以后,队列大小可通过
- 解决方案
- 无效连接监视释放:不停监视所有连接(包括三次握手和只握手一次的),当达到一定阈值时拆除这些连接,释放系统资源。但这种方法对正常连接和攻击连接一视同仁,不推荐;
- 延缓 TCB 分配方法:一般第一次握手后服务器需为请求分配 TCB(连接控制资源,约需 200 多字节),延迟 TCB 分配,等正常连接建立后再分配,可有效减轻服务器资源消耗;
- 使用防火墙:防火墙确认连接有效性后,才向内部服务器(Listener)发起 SYN 请求。
3.3 TCP 四次挥手
3.3.1 过程
-
断开 TCP 连接时,客户端和服务端总共发送 4 个包以确认连接断开,在 socket 编程中由客户端或服务端任一方执行
close
触发。因为 TCP 连接是全双工的,每个方向都需单独关闭,先关闭的一方执行主动关闭,另一方执行被动关闭; -
简易速记版:
-
详细细节版:
-
过程(以客户端主动关闭为例):
-
客户端应用进程调用
close
执行主动关闭,其 TCP 发送一个 FIN(Finish)分节(FIN = 1,序列号 seq = u),表示数据发送完毕,进入 FIN-WAIT-1(终止等待 1)状态;分节(segment)指的是 TCP 传输数据时的基本单位,是对数据进行封装处理后的一种格式;
-
服务器端收到 FIN 后执行被动关闭,发出确认报文(ACK = 1,序列号 seq = v,确认号 ack = u + 1),进入 CLOSE-WAIT(关闭等待)状态(此时为半关闭状态,主动关闭端无数据发送,但被动关闭端若发送数据,主动关闭端仍需接受);客户端收到确认报文后进入 FIN-WAIT-2(终止等待 2)状态;
-
一段时间后,服务器端应用进程调用
close
关闭套接字,其 TCP 发送一个 FIN(FIN = 1,ACK = 1,序列号 seq = w,确认号 ack = u + 1),表示无数据需要发送了; -
客户端(原主动关闭端)收到最终 FIN 后,确认并发出 ACK 报文(ACK = 1,序列号 seq = u + 1,确认号 ack = w + 1),进入 TIME-WAIT(时间等待)状态。需经过 2×MSL2\times MSL2×MSL 时间后,撤销相应 TCB,进入 CLOSED 状态。服务器端收到客户端的确认后,立即进入 CLOSED 状态,撤销 TCB 结束 TCP 连接(被动关闭端结束连接时间比主动关闭端早);
MSL:最长报文段寿命,RFC 1122 建议值 2 分钟,源自 Berkeley 的实现传统用 30 秒,故 TIME_WAIT 持续时间在 1 分钟到 4 分钟之间;
-
-
通常需要 4 个分节,某些情形下步骤 1 的 FIN 可随数据一起发送,步骤 2 和步骤 3 的分节也可能被合并成一个分节。
3.3.2 为什么 TCP 挥手需要四次
- TCP 是全双工连接,必须两端同时关闭连接才算真正关闭;
- 一方准备关闭写操作时,仍可读取另一方发送的数据,发送 FIN 结束报文给对方,对方收到后回复 ACK 报文;当这方也写完准备关闭,发送 FIN 报文,对方回复 ACK,两端都关闭,TCP 连接正常关闭。
3.3.3 为什么需要 TIME-WAIT 状态
- 可靠终止 TCP 连接:客户端收到服务器的 FIN 报文后必须发出确认,若最后这个 ACK 报文丢失,服务器未收到会重发 FIN 报文,客户端需在 TIME-WAIT 状态等待该 FIN 报文并回复确认,以可靠终止连接;
- 保证迟来的 TCP 报文被识别并丢弃:Linux 系统中一个 TCP 端口不能同时打开多次,若不存在 TIME-WAIT 状态,应用程序可立即建立与刚关闭连接相似(相同 IP 地址和端口号)的新连接,新连接可能受到原来连接迟来的报文段影响,而 TIME-WAIT 状态可避免这种情况。
3.3.4 MySQL 数据库大量 TIME_WAIT 的解决方法
- MySQL 参数调整:通过
mysql> show variables like "time_timeout";
查看wait_timeout
(针对非交互式连接,控制连接最大空闲时长,默认 28800 秒即 8 小时),可根据需要调整该参数; - 调整内核参数:
- 编辑
/etc/sysctl.conf
文件,加入以下内容:net.ipv4.tcp_syncookies = 1
:开启 SYN Cookies,当 SYN 等待队列溢出时,启用 cookies 处理,防范少量 SYN 攻击,默认 0(关闭);net.ipv4.tcp_tw_reuse = 1
:开启重用,允许将 TIME - WAIT sockets 重新用于新的 TCP 连接,默认 0(关闭);net.ipv4.tcp_tw_recycle = 1
:开启 TCP 连接中 TIME - WAIT sockets 的快速回收,默认 0(关闭);net.ipv4.tcp_fin_timeout = 30
:修改系统默认的 TIMEOUT 时间;
- 然后执行
/sbin/sysctl -p
让参数生效;
- 编辑
- 可能产生的原因:连接 MySQL 的代码使用短连接,用完后系统自动回收资源,因访问量巨大产生很多连接;程序代码中没有使用
mysql.close()
,导致 MySQL 空闲判断机制生效。
4 实战观察 TCP 报文
4.1 抓包的目的
- 定位网络问题:
- 发送数据给后台但后台未收到时,可抓包分析是后台处理问题、数据未发出还是发送数据格式有误;
- 与后台接口联调测通但业务数据对不上时,抓包可确认问题所在;
- 线上出现 bug 且无法调试代码时,可直接抓包分析;
- 系统性能不佳时,抓包查看接口响应时长,判断是否为后台性能问题;
- 学习网络协议:使用抓包工具分析网络数据更直观。常用抓包工具有 F12(浏览器自带)、Fiddler、Charles、Wireshark,其中 Wireshark 在支持协议、用户友好度、开源免费、程序支持及操作系统兼容性等方面表现出色,是最常用的抓包和报文分析工具。
4.2 Wireshark 的下载与安装
-
官网:Wireshark • Go Deep;
-
点击“Download Now”进入下载页面,选择适合自己的版本下载。
4.3 实战:用 Wireshark 看 TCP 三次握手
4.3.1 准备工作
-
打开一个 MySQL 客户端,准备连接 IP 地址为 47.112.44.148 的云端 MySQL;
-
设定捕获过滤器,只捕获与该 IP 地址相关的数据包(过滤条件:
host 47.112.44.148
); -
开始捕获后连接数据库,Wireshark 会捕获到本机与该 IP 通信的报文;
-
为观察 TCP 三次握手和四次分手报文,在显示过滤器中设置
tcp and!mysql
; -
TCP 三次握手规则包含一个 SYN 包、一个 SYN/ACK 包和一个 ACK 包;
-
就是窗口里最上面的三条记录,下面一条一条来看:
4.3.2 第一次握手
-
数据链路层:可看到源地址(与下图显示的机器上的 MAC 地址一致,如上图中的
B0-25-AA-35-A2-BE
)等相关信息; -
IP 层:表明上一层协议是 TCP,同时显示本地 IP 地址(如
192.168.0.154
)和远程服务器 IP 地址(47.112.44.148
); -
TCP 层:包含本地端口(如
55940
)和远程服务器端口(如3306
),SYN 字段被设置为 1,表明这是一个 SYN 包,还带有本次通信的 seq 值(如1979849485
);
4.3.3 第二次握手
-
直接查看 TCP 层报文,这是服务器给客户端的 ACK 报文,包含远程服务器端口(
3306
)和本地端口(55940
)。服务器会告知客户端自己的 seq 值(如3366556883
),并对客户端传递的 seq 值(第一次握手的1979849485
)做应答确认(Acknowledgment number 为1979849486
,即第一次握手 seq 值加 1)。TCP 报文格式中的 SYN 字段和 Acknowledgment 字段都被设置为 1,表明这是一个 SYN/ACK 包;
4.3.4 第三次握手
-
报文包含源端口(
55940
)、目的端口(3306
)等信息,Sequence number 等字段也符合三次握手的逻辑,可结合前两次握手的分析方法自行分析;
5 UDP和UDT、QUIC
5.1 UDP(用户数据报协议)
- UDP(User Datagram Protocol),即用户数据包协议,该协议把数据直接发出去,不管对方是否接收、能否接收,也不需要接收方确认,属于不可靠传输,可能出现丢包现象,实际应用中需程序员编程验证;
- 单播和广播
- 单播:发送消息给由唯一地址标识的单一网络目的地,面向连接和无连接协议都支持这种模式;
- 广播:因通讯无需连接,可传输到网络(或子网)上的所有主机;
- 应用场景:因没有 TCP 等复杂机制,使用广泛。包括:
- NTP(网络时间协议)、DNS(也使用 TCP)等包总量较少的通信;
- 视频、音频等多媒体即时通信;
- 限定于 LAN 等特定网络中的应用通信;
- DHCP 等利用 UDP 广播功能的协议;
- QQ 以 UDP 为主、TCP 为辅。
5.2 UDT
- 基于 UDP(UDP-based Data Transfer Protocol)的数据传输协议是一种互联网数据传输协议,主要目的是支持高速广域网上的海量数据传输,典型例子如光纤广域网上的网格计算(用于远程访问仪器、分布式数据挖掘和高分辨率多媒体流等场景);
- 背景:互联网标准数据传输协议 TCP 在高带宽长距离网络上性能很差,UDT 建于 UDP 之上,引入新的拥塞控制和数据可靠性控制机制,是面向连接的双向应用层协议;
- 特性:
- 基于 UDP 的应用层协议:兼顾 TCP 协议的安全可靠和 UDP 协议的高效;
- 面向连接的协议:两个应用交换数据前需先建立连接,连接维护基于握手、Keep-alive(保活)及关闭连接;
- 可靠的协议:依靠包序号机制、接收者的 ACK 响应和丢包报告、ACK 序号机制、重传机制(基于丢包报告和超时处理)实现数据传输可靠性;
- 双工的协议:每个 UDT 实例包含发送端和接收端的信息;
- 新的拥塞算法与可扩展的拥塞控制框架:拥塞控制算法是混合的基于窗口、基于速率的,不同于 TCP 基于窗口的慢启动和拥塞避免算法;可扩展的框架开源且有 C++类架构,支持开发者派生专用拥塞控制算法;
- 带宽估计:使用对包(PP - Packet pair)机制,每 16 个包为一组,最后一个是对包,发送方无需等到下一个发送周期发送。接收方收到对包后记录到达时间,结合上次记录值用中值过滤法计算链路带宽,并在下次 ACK 中反馈。
5.3 QUIC
- QUIC 代表“快速 UDP Internet 连接”,基于 UDP 的传输层协议,是 Google 尝试将 TCP 协议重写,结合 HTTP/2、TCP、UDP 和 TLS(用于加密)等技术的改进技术;
- 目的:整合 TCP 协议的可靠性和 UDP 协议的速度与效率,希望逐渐取代 TCP 和 UDP,作为 Internet 上移动二进制数据的新选择协议;
- 由于 TCP 是在操作系统内核和中间件固件中实现的,因此对 TCP 进行重大更改几乎是不可能的(TCP 协议栈通常由操作系统实现,如 Linux、Windows 内核或者其他移动设备操作系统。修改 TCP 协议是一项浩大的工程,因为每种设备、系统的实现都需要更新)。但是,由于 QUIC 建立在 UDP 之上,因此没有这种限制;
- 优势
- 多路复用:一个连接可同时承载多个流(stream),同时发起多个请求,请求间完全独立,某个请求阻塞或报文出错不影响其他请求;
- 快速建立连接:只需要 1RTT(Round-Trip Time)延迟就能建立可靠安全的连接,比 TCP + TLS 的 3 次 RTT 更快捷,且客户端可本地缓存加密认证信息,再次连接时实现 0 - RTT 连接建立延迟;
- 纠错机制:TCP 采用重传机制,丢包时需等待延时判断丢包后启动重传,造成阻塞;QUIC 采用类似 RAID5 的纠错机制,每 n 个包额外发一个校验和包,若丢一个包,可通过其他包和校验和恢复,无需重传;
- 快速迭代更新:直接基于客户端(应用进程)实现,而非内核,无需操作系统层面改造,部署灵活;
- 连接保持:在客户端保存连接标识,当客户端 IP 或端口变化时,可快速恢复连接。客户端以标识请求服务端,服务端验证标识后感知客户端新地址端口并重新关联,继续通讯,改善移动端应用连接体验(如从 WiFi 切换到流量)。