要说现在网络世界里最牛掰的存在,那 TCP/IP 协议绝对得算一个,简直就是互联网的顶梁柱,全球的电脑能互相串门、传消息,全靠它撑着。

今儿个咱就好好扒一扒这 TCP/IP 协议的架子、干活的门道,再整点实际例子,保准让你把这复杂玩意儿整明白。

估计不少哥们儿以为 TCP/IP 就是个协议,要么就是 TCP 和 IP 俩兄弟的合称,其实它是一整个协议家族,人称“网络江湖十二钗”,

里面成员老多了,像 IP、ICMP(互联网控制报文协议)、TCP、HTTP(超文本传输协议)、FTP(文件传输协议)、POP3(邮局协议)啥的,都在这家族里待着。

简单讲,TCP/IP就是一套通信黑话

就像你跟东北老铁说“整点嘎哈呢”,南方人听不懂,但只要大家都说TCP/IP这套黑话,不管你是Windows、Mac还是Linux,都能愉快地互发“在吗”和“点个关注”。

一、TCP/IP协议族

TCP/IP协议族包括许多协议,其中一些最重要的包括:

  1. IP协议(Internet Protocol)作为网络层核心协议,IP协议通过IP地址实现主机寻址,并负责数据包的路由选择和分组转发。

  2. TCP协议(Transmission Control Protocol)传输层面向连接的可靠协议,提供有序传输、差错控制、流量控制和拥塞控制机制,典型应用于要求数据完整性的场景。

  3. UDP协议(User Datagram Protocol)无连接的轻量级传输协议,以低开销实现高效数据传输,适用于实时性要求高于可靠性的应用(如流媒体、VOIP)。

  4. ICMP协议(Internet Control Message Protocol)网络诊断协议,主要用于传递网络状态信息(如ping响应)和错误报告(如目标不可达)。

  5. ARP协议(Address Resolution Protocol)完成网络层(IP地址)到数据链路层(MAC地址)的地址解析,保障局域网内设备通信。

  6. HTTP协议(Hypertext Transfer Protocol)应用层协议,作为Web通信的基础,支持客户端-服务器模式的超文本数据传输(HTTPS为其安全版本)。

  7. FTP协议(File Transfer Protocol)实现跨网络文件传输的标准协议,支持认证、目录操作及双向文件传输。

  8. SMTP协议(Simple Mail Transfer Protocol)电子邮件传输的核心协议,规定了邮件服务器间的通信规则和中继流程。

  9. DNS协议(Domain Name System)分布式命名系统,将人类可读的域名转换为机器可识别的IP地址,是互联网的重要基础设施。

二、TCP/IP 协议和七层 OSI 模型的对应关系

图片

你可能听过OSI七层模型,听着贼高大上,啥物理层、数据链路层、会话层……每层都有自己的活儿和协议,还得跟隔壁层打好交道。

但现实是——这玩意儿太理想化,实战中根本没人用!就像你学驾照先背《交通法》全文,结果上路全是“老司机带带我”。

应用层

HTTP、SMTP、SNMP、FTP、Telnet 这些都在这儿待着

表示层

XDR、ASN.1、SMB 这些是这儿的常客

会话层

ASAP、SSH、RPC 这些在这儿负责搭话

传输层

TCP、UDP、TLS 这些在这儿管传输

网络层

IP、ICMP、IGMP、ARP 这些在这儿找路

数据链路层

以太网、Wi-Fi、PPP 这些在这儿管链路

物理层

同轴电缆、光纤、网线这些实实在在的东西就在这儿

注:ARP 这货比较特殊,在二层和三层之间晃悠。

而TCP/IP呢?它更接地气,直接来个五层架构,简单粗暴,主打一个能用就行:

  • 物理层:就是网线、光纤、WiFi信号这些“肉身”,说白了就是电线杆子和电磁波

  • 链路层(数据链路层):负责在“同一局域网”里找人,靠的是MAC地址——相当于设备的“身份证号”。你家路由器认的就是这个。

  • 网络层:这层的扛把子就是IP协议,负责跨网络寻路,就像快递小哥看地址送货,IP就是你的“门牌号”。

  • 传输层:这层有两个狠人——TCP和UDP。一个稳如老狗,一个浪如疯狗。

  • 应用层:这就是你天天打交道的APP们,比如HTTP(刷网页)、FTP(传文件)、SMTP(发邮件)——全是人精。

举个栗子:你刷视频号,数据从手机出发,一层层往下打包:应用层写“我要看小姐姐”,传输层盖个TCP章说“这包必须送到”,网络层贴个IP地址“发到抖音服务器”,链路层再贴个MAC地址“先发给路由器”,最后物理层变成电信号“嗖”地飞出去——一套连招,丝滑!

注:数据链路层与物理层通常被称为网络接口层。

三、传输层双雄:TCP 和 UDP

1.TCP/IP 协议的应用层

应用层里的协议都跟应用程序搭伙干活,利用底层网络传应用程序的业务数据。一些特定程序就靠这层运行,这层协议能直接帮用户应用干活。像 HTTP(管网页的)、FTP(传文件的)、SMTP(发邮件的)、SSH(安全远程登录的)、DNS(解析域名的),还有好多其他协议,都在应用层待着。

2.TCP/IP 协议的传输层

传输层的协议能解决端到端的可靠性问题,保证数据靠谱地到地方,甚至能保证数据按顺序到。它的主要活儿大概有这些:

(1)给端到端的连接提供传输服务;

(2)这种服务分靠谱和不靠谱的,TCP 就是典型的靠谱传输,UDP 就不太靠谱;

(3)还能管端到端连接的流量、差错、服务质量这些事儿。

传输层主要有俩脾气不一样的协议:TCP 传输控制协议UDP 用户数据报协议

TCP 协议:这货得先连上才能传数据,而且特靠谱,能保证数据完整、没损坏,还按顺序到。它还会时不时看看网络负载,控制发数据的速度,免得网络受不了。另外,它还会尽量按规定顺序发数据。

UDP 协议:这货不用先连接,发数据就跟扔快递似的,不管对方收没收到,也不保证数据按顺序到。

总的来说,TCP 传数据慢是慢了点,但靠谱;UDP 速度快,就是没那么靠谱,适合传那些对可靠性要求不高、又不大的数据,比如 QQ 聊天的消息。

3.TCP/IP 协议的网络层

TCP/IP 协议的网络层,就是在复杂的网络里给要发的数据包找条合适的路。简单说,就是负责把数据传到目标地址,哪怕那地址是好几个网络通过路由器连起来的也能找到。另外,它还能搞定拥塞控制、网际互连这些事儿。网络层的代表协议有 ICMP、IP、IGMP 这些。

4.TCP/IP 协议的链路层

链路层有时候也叫数据链路层或者网络接口层,专门处理连接网络的硬件部分。这层不光有操作系统里的设备驱动、网卡、光纤这些能看见的东西,还有连接器之类的所有传输用的媒介。在这层,数据是以比特为单位传输的。主要协议有 ARP、RARP 这些。

四、物理层:用 MAC 解决设备的身份证问题

通信的原始时代:

假设你是一台电脑,名字叫 A

图片

老早以前,你孤零零的,不跟任何电脑来往。

后来有一天,你想跟另一台电脑 B 说说话,于是你们俩各开了个网口,用一根网线连起来了。

图片

你肯定纳闷,一根网线咋就不能通信了?我可以跟你扯 IO、中断、缓冲区,但咱现在研究网络,就别纠结这个了。

你要是实在想不通,要么去研究研究操作系统咋处理网络 IO 的,要么去看看包是咋被网卡变成电信号发出去的,要么就当电脑里有个小人在开枪发信号得了~

图片

反正,你们俩就是连上了,能唠嗑了。

有一天,又来了个新朋友 C,你们很快发现,每人开两个网口,用三根网线,就能互相都连上。

图片

可随着人越来越多,你身上的网口不够用了,网线也乱得跟蜘蛛网似的。

图片

于是你们发明了个中间设备,把网线都插上面,让它帮忙转发消息,这样就能互相通信了。本质上跟以前一样,就是网口和网线少了,没那么乱了。

图片

你给这玩意儿取名叫集线器,它就是个憨憨,只会把电信号转发到所有出口(广播),啥也不会处理,你觉得它没智商,就把它归到物理层了。

图片

既然都转发到所有出口了,那 BCDE 四台机器咋知道数据包是不是给自己的呢?

首先,得给所有连到交换机的设备起个名字。以前叫 ABCD 太 low 了,现在得整个全局唯一的高端名字当标识,你管这名字叫MAC 地址

你的 MAC 地址是 aa-aa-aa-aa-aa-aa,伙伴 B 的是 bb-bb-bb-bb-bb-bb,以此类推,只要不重名就行。

这样一来,A 给 B 发数据包的时候,只要在开头加上目标 MAC 地址,B 收到后一看,是给自己的,就收下;CDE 收到后一看,不是给自己的,就扔了

虽然集线器让布局干净多了,但我只想给 B 发的消息,现在所有电脑都能收到,既不安全,又浪费网络资源。

五、数据链路:用交换机解决 MAC 地址映射问题

要是能把集线器弄聪明点,只发给目标 MAC 地址对应的电脑,那就完美了。

就多了这么个功能,这玩意儿就显得有智商了,你给它取名叫交换机。也正因为这一点点聪明,你把它放到了另一个层级 ——数据链路层

图片

你是这么设计的:交换机里面有张 MAC 地址表,记着每个 MAC 地址的设备连在哪个端口上。

MAC 地址

端口

bb-bb-bb-bb-bb-bb

1

cc-cc-cc-cc-cc-cc

3

aa-aa-aa-aa-aa-aa

4

dd-dd-dd-dd-dd-dd

5

比如你要给 B 发个数据包,构造好数据从网口发出去,到了交换机,交换机一查 MAC 地址表,发现目标 B 的 MAC 地址 bb-bb-bb-bb-bb-bb 在 1 号端口,就直接从 1 号端口发给 B,齐活~

你把用这种方式连起来的小网络,叫做以太网

当然,刚开始的时候 MAC 地址表是空的,那它是咋慢慢填满的呢?

假设 MAC 地址表是空的,你给 B 发了个数据包。

这个包从 4 号端口进的交换机,交换机就赶紧在 MAC 地址表记上:

MAC:aa-aa-aa-aa-aa-aa
端口:4

交换机一看,目标 MAC 地址(bb-bb-bb-bb-bb-bb)在表里没记录,就把这包发给了所有端口,也就是所有机器。

之后,只有 B 收到了给自己的包,就回复了一下,回复的数据从 1 号端口进了交换机,交换机又赶紧记上:

MAC:bb-bb-bb-bb-bb-bb
端口:1

图片

就这么着,网络里的机器来回通信,交换机的 MAC 地址表慢慢就记满了~

机器越来越多,交换机的端口又不够了,不过你很聪明,发现把多个交换机连起来,这问题就解决了~

图片

你根本不用额外设计啥,就按之前的规矩来,像上面那样接线,所有电脑就能互联,所以交换机这设计,是真的妙。你琢磨琢磨为啥(比如 A 要给 F 发数据)。

不过你得注意,上面那根青色的线,在 MAC 地址表里可不是一条记录,而是要把 EFGH 这四台机器和对应的端口(端口 6)都记上。

MAC 地址和端口咋对应起来的

说到底,俩交换机最后都会记下 A 到 H 所有机器的对应关系

左边的交换机是一套

图片

右边的交换机又是一套。

图片

这在只有 8 台电脑的时候还好说,哪怕几百台,也还能应付,所以交换机这设计,确实撑了好一阵子。

但咱都知道,人这贪心劲儿啊,没多久电脑数量就涨到几十万、亿级了。

六、传输层:IP 地址和路由器这俩货

交换机哪记得住这么多对应关系啊,直接歇菜了。

这时候你就动了歪脑筋:问题出在那根青色的网线上,后面不知道接了多少设备,地址表才越变越大。

那能不能让这根青网线接个新设备?这设备得跟电脑似的,有自己独一份的 MAC 地址,还能帮着转发数据包。

这设备就是路由器,功能就是:自带 MAC 地址,还能转发数据包。你把它归到了网络层

图片

注意啊,路由器每个端口,都有自己独立的 MAC 地址。

现在好了,交换机的 MAC 地址表里,只要多一条 MAC 地址 ABAB 和对应端口的记录,就能把数据包转给路由器,这事儿就搞定了。

可咋让发给 C、D,甚至 DEFGH... 的数据包,都先发给路由器呢?

你可能会想:要是 C 和 D 的 MAC 地址有共同前缀,比如 C 是 FFFF-FFFF-CCCC,D 是 FFFF-FFFF-DDDD,那只要是 FFFF-FFFF - 开头的,全发给路由器不就行?

想法不错,但现实是:行不通

这时IP 地址横空出世

咱先瞅瞅现实中 MAC 地址的结构。MAC 地址也叫物理地址、硬件地址,48 位长,一般写成 00-16-EA-AE-3C-40 这样。

这地址是设备出厂时烧在网卡里的,前 24 位是厂商编号,后 24 位是厂商自己编的序列号。只要不瞎改,全世界就这一个,跟身份证号似的,独一份。

可你要是想让某一类 MAC 地址的设备都走路由器,就得让同一子网的设备全买一个厂商的,还得让厂商按你的子网规划烧地址,以后网络结构还不能改 —— 这不是扯吗?

于是你搞了个新地址,给每台机器整个 32 位的编号,比如 11000000101010000000000000000001。

看着费劲,分成四段:11000000.10101000.00000000.00000001,再转成十进制:192.168.0.1。

你给这地址起了个响亮的名儿 ——IP 地址。现在每台电脑,既有固定的 MAC 地址,又有能随便改的 IP 地址,IP 是软件层面的,想改就改,MAC 一般动不了。

这能改的 IP 地址,就能按你规划的网络结构调整了。

图片

比如你想给 ABCD 发数据,不管哪台,都可以说:“IP 地址是 192.168.0 开头的,全发给路由器,后面咋传,让它搞定!” 是不是特巧妙?

路由器就这么来了,专门管 IP 地址的寻找。那数据包给了路由器,它咋准确发给目标设备呢?

别急,咱慢慢说。

先给组网里的设备都配上 IP 地址。

图片

现在俩设备传数据,除了加数据链路层的头部,还得加个网络层的头部。

比如 A 给 B 发数据,因为直接连交换机,A 直接发下面这样的包就行,网络层还显不出作用。

图片

但要是 A 给 C 发数据,就得先给路由器,再由路由器转给 C。底层还得靠以太网,所以数据包得分两段走。

A 到路由器这段的包是这样的:

图片

路由器到 C 这段的包是这样的:

图片

估计细心的哥们儿对 A->B 和 A->C 这两种情况有不少疑问,咱一个个说。

子网是咋来的

A 给 C 发数据包,咋知道要不要经过路由器转发呢?

答案:子网

要是源 IP 和目的 IP 在一个子网,直接通过交换机发;不在一个子网,就丢给路由器。

那啥叫在一个子网?

  • 192.168.0.1 和 192.168.0.2 算一个子网

  • 192.168.0.1 和 192.168.1.1 就不是一个子网

这是咱规定的:192.168.0.xxx 开头的,算一个子网,不然就不是。

电脑咋知道这规矩呢?于是就有了子网掩码这东西。

比如某台机器的子网掩码是 255.255.255.0,意思就是:源 IP 和目的 IP 分别跟这掩码做与运算,结果一样就是一个子网,不一样就不是,就这么简单。

举个栗子:

  • A 电脑:192.168.0.1 & 255.255.255.0 = 192.168.0.0

  • B 电脑:192.168.0.2 & 255.255.255.0 = 192.168.0.0

  • C 电脑:192.168.1.1 & 255.255.255.0 = 192.168.1.0

所以 A 和 B 是一伙的,C 自己一伙,A 和 C 不是一伙的。

图片

A 给 C 发消息,一算不在一个子网,就把包扔给路由器,之后咋传,A 才不管呢。

A 咋知道哪个是路由器呢?

答案:在 A 上设默认网关

A 判断出 C 不在一个子网,得发路由器,可路由器 IP 是多少?

其实说发给路由器不准确,A 是发给默认网关。对 A 来说,只能直接发同一个子网的 IP,至于是路由器还是别的电脑,它才不管,只要那设备有 IP 就行。

所以默认网关就是 A 电脑里设的一个 IP,发不同子网的机器时,就发这个 IP。

图片

就这么简单!

路由表的由来(跟 MAC 表一样,都是被逼出来的)

路由器咋知道 C 在哪儿呢?

答案:路由表

A 把数据包成功发给路由器了,最后一个问题:路由器咋知道这包该从自己哪个端口发出去,才能到 C 那儿(不管直接还是间接)?

路由器收到的包有目的 IP(就是 C 的 IP),得转成从哪个端口出,很容易想到:整个表,跟 MAC 地址表似的。

这表就叫路由表

至于路由表咋来的,有一堆路由算法,咱这儿不说 —— 因为我也不懂~

跟 MAC 地址表不一样,路由表不是一对一的明确关系。咱看个路由表结构。

图片

有种简写方式:192.168.0.0(255.255.255.0)可以写成 192.168.0.0/24,意思是前 24 位表示子网。

图片

路由表就表示:192.168.0.xxx 这个子网的,都从 1 号端口发。下一跳列先不管。

结合结构图:

图片

刚才说的都是 IP 层,可发数据包的数据链路层要 MAC 地址,我只知道 IP 地址咋整?

答案:ARP

假设你(A)不知道 B 的 MAC 地址(现实中本来就不知道,之前是假设知道),只知道 B 的 IP 是 192.168.0.2,咋把包准确发给 B?

简单,在网络层找到 IP 对应的 MAC 地址,也就是通过某种方式,找到 192.168.0.2 对应的 MAC 地址 BBBB。

这方式就是ARP 协议,A 和 B 电脑里还有张ARP 缓存表,记着 IP 和 MAC 的对应关系。

ip地址

mac地址

192.168.0.2

BBBB

一开始这表是空的,A 想知道 B 的 MAC,就广播一条 ARP 请求,B 收到后,带上自己的 MAC 回复 A。A 就更新自己的 ARP 表了。

就这么着,大家不断广播 ARP 请求,最后所有电脑的 ARP 缓存表都填全了。

七、整个传输过程

总结一下,就几条规矩:

1、电脑视角

  • 先知道自己的 IP 和对方的 IP

  • 用子网掩码判断是不是一个子网

  • 一个子网就用 ARP 找对方 MAC,直接发

  • 不是一个子网就用 ARP 找默认网关的 MAC,直接发

2、交换机视角

  • 收到的包必须有目标 MAC 地址

  • 查 MAC 地址表找对应端口

  • 找到了就从指定端口发

  • 没找到就所有端口都发

3、路由器视角

  • 收到的包必须有目标 IP 地址

  • 查路由表找对应端口

  • 找到了就从指定端口发(不在任何子网范围,走路由器的默认网关也叫找到)

  • 没找到就返回 “路由不可达” 的包

嗅觉灵的哥们儿肯定能感觉到:网络层(IP 协议)自己不能传包,实际是靠数据链路层(以太网的交换机)传的。

涉及到三张表

  • 交换机有MAC 地址表,对应 MAC 和端口

  • 路由器有路由表,对应 IP 段和端口

  • 电脑和路由器都有ARP 缓存表,对应 IP 和 MAC

这三张表咋来的

  • MAC 地址表:以太网里的设备通过交换机通信,慢慢填起来的

  • 路由表:各种路由算法 + 人工配置弄起来的

  • ARP 缓存表:不断发 ARP 请求填起来的

知道这些,网络上俩节点咋发数据包的过程,就全整明白了!

咱放最后一个网络拓扑图,做好战斗准备!

图片

这时路由器 1 连了路由器 2,路由表里就有了下一跳地址。匹配到有下一跳的,得再找端口,再找下一跳 IP 的 MAC 地址。

图片

说白了,最后必须能对应到一个端口,从那儿把包发出去。

现在 A 给 F 发数据包,能通吗?通的话过程是啥样的?

图片

详细过程文字描述

  1. 首先 A(192.168.0.1)用子网掩码(255.255.255.0)一算,自己和 F(192.168.2.2)不在一个子网,决定发给默认网关(192.168.0.254)

  2. A 通过 ARP 找到默认网关 192.168.0.254 的 MAC 地址。

  3. A 把源 MAC(AAAA)和网关 MAC(ABAB)装在数据链路层头部,再把源 IP(192.168.0.1)和目的 IP(192.168.2.2)装在网络层头部(注意啊,这俩 IP 从头到尾不变,只有 MAC 在变),然后发包。

    图片

  4. 交换机 1 收到包,一看目标 MAC 是 ABAB,转发给路由器 1。

  5. 路由器 1 收到包,目标 IP 是 192.168.2.2,查路由表,发现下一跳是 192.168.100.5。

  6. 路由器 1 得干两件事:再查路由表,匹配到端口 2,装到数据链路层,从 2 号口发出去。

  7. 路由器 2 收到包,目标 IP 是 192.168.2.2,查路由表,匹配到端口 1,准备从 1 号口发。

  8. 路由器 2 得知道 192.168.2.2 的 MAC,查 ARP 缓存,找到是 FFFF,装在数据链路层头部,从 1 号口发出去。

  9. 交换机 3 收到包,目标 MAC 是 FFFF,查 MAC 地址表,该从 6 号口出,就从 6 号口发。

  10. F 终于收到包,一看目标 MAC 是自己,就收下了!

八、HTTP 报文传输原理

用 TCP/IP 通信时,数据包会按分层顺序跟对方通信。发送端从应用层往下走,接收端从链路层往上走。从客户端到服务器,每一帧数据的路都是:应用层 -> 运输层 -> 网络层 -> 链路层 -> 链路层 -> 网络层 -> 运输层 -> 应用层。

以 HTTP 请求为例,从浏览器到服务器的过程,大概就像下图那样。

图片

数据在网上传,不能光秃秃的,不然就乱套了。发的时候加特定标识,这叫封装;用的时候去掉标识,这叫分用。TCP/IP 的封装和分用,大概如下图

图片

封装时,每过一层就加该层的头部;分用时,每过一层就删该层的头部。

传输层封装时,首部要存应用程序的标识,TCP 和 UDP 都用 16 位端口号,还会存源端口和目的端口。

网络层封装时,IP 首部会标上层协议类型,用 8 位数值:1 是 ICMP,6 是 TCP,17 是 UDP 啥的。还会标源 IP 和目标 IP。

链路层封装时,以太网帧首部有 16 位类型域,标上层协议类型,比如 IPv4、ARP 啥的。

总的来说,TCP/IP 分层管理、封装分用的好处:改设计时只换变动的层;接口定好后,每层内部随便改;分层后设计变简单,每层只管自己的活儿。

TCP/IP 和 OSI 的区别:OSI 注重 “通信协议该有啥功能”,TCP/IP 更强调 “在电脑上实现协议该开发啥程序”。

实际上,数据报文会在不同物理网络间传,还是以 HTTP 请求为例,过程大概如下图。

图片

不同物理网络间传包,网络层靠路由器存包、分组转发。把俩网络用路由器连上,就组成了互联网。路由器就是个特殊硬件盒,能连以太网、令牌环网这些不同网络。

物理网络用路由器连起来,就算加很多路由器,应用层也没啥感觉,TCP 协议栈把物理层的复杂藏起来了。就因为这,TCP/IP 传输才这么牛。

接下来,咱说说跟传输性能关系大的:TCP 的三次握手建连接,四次挥手断连接。不过先得说说 TCP 报文协议。

九、TCP 协议的报文格式

在 TCP/IP 协议栈里,IP 层只管让数据跨网络,不管咋传。整个协议栈一起配合,让数据通过无数点对点通路传到目的地,一段通路叫一 “跳”(hop)。

传输层 TCP 协议提供面向连接、可靠的字节流服务,数据帧格式大概如下图。

图片

TCP 数据帧有这些字段:

(1)源端口号:16 位,标出发送端口。源端口 + 源 IP,能标出发送地址。

(2)目的端口号:16 位,标出接收端口。目的端口 + 目的 IP,能标出接收地址。

(3)序号(Sequence Number):32 位,发送端发的字节流里,每个字节都有编号。发数据时,都得标序号。

序号的意思跟 SYN 控制标志有关:

  • SYN=1 时,是建连接阶段,序号是初始序号 ISN(随机生成);

  • SYN=0 时,正式传数据,第一个报文序号是 ISN+1,后面的是前一个序号 + 数据字节数(不算 TCP 头)。比如一个包数据 12 字节,序号 5,下一个序号就是 5+12=17。

传数据时,TCP 用序号保证数据流有序。发送端用序号跟踪发了多少;接收端用序号识别重复包、给乱序包排序。

(4)确认序号(Acknowledgment Number)

标接收端期望收到的字节序列。如果 ACK 控制位是 1,确认序号就是下一个想收到的包的序号。

比如 Client 发 3 个 1000 字节的包,起始序号 1,Server 收到一个就回复 ACK:第一个 ACK 是 1+1000=1001,盼着下一个序号 1001;第二个 ACK 是 1001+1000=2001,盼着下一个 2001。

要是 Server 处理第二个包出错,还回复 1001,Client 就得重发第二个包。

只有 ACK 标志为 1 时,确认序号才有用。建连接后,所有报文的 ACK 都得是 1;SYN 类型的报文 ACK 是 0,没确认序号。

图片

(5)头部长度

4 位,标 TCP 首部长度,单位是 4bit。不是字节数,是 32bit 的数目,所以 TCP 头部最多 60 字节(4*15)。没选项的话 20 字节,头部长度就是 5(20/4=5)。

(6)预留 6 位

没啥用,先留着。

(7)控制标志

6 个 bit,有 URG、ACK、PSH、RST、SYN、FIN。建连接时,单个 SYN 是请求,SYN+ACK 是响应。

(8)窗口大小

16 位,用来流量控制,是本端一次想收的字节数。

(9)校验和计算

16 位,对整个 TCP 报文(头 + 数据)算校验和,接收端用来验证。

(10)紧急指针

16 位,是个偏移量,加 SN 序号就是紧急数据最后一个字节的序号。

以上 10 项是必须的,20 字节。后面是可选项和填充部分。

(11)可选项和填充部分

长度是 4n 字节,根据需要加选项。不够的话填 0,确保是 4 字节的倍数。

最常见的是 MSS(最长报文大小),建连接时第一个包(SYN=1)里标,是本端能接受的最大数据块长度。一方不接收对方的 MSS,就定为 536 字节。一般 MSS 越大越好,能提高网络利用率。

所以 TCP 首部最小 20 字节。首部后面是数据部分,可选。建连接、断连接时,交换的报文可能只有首部;没数据要发时,也可能用空首部确认收到的数据。

总的来说,TCP 的可靠性靠这些:

  1. 按 MSS 分割应用数据,这叫协商机制。

  2. 重传:设定时器,超时没收到确认就重发。

  3. 校验:对首部和数据校验。

  4. 排序:接收端给数据排序,再给应用层。

  5. 去重:接收端丢重复数据。

  6. 流量控制:靠滑动窗口。

好了,TCP 报文格式说完了。接下来重点说三次握手建连接,四次挥手断连接。

十、TCP 的三次握手

TCP 建连接得三次握手,断连接得四次挥手,这里面都干了啥?咋进行的?

三次握手过程

  1. 第一次握手:Client 进入 SYN_SENT 状态,发个 SYN 帧求连接。SYN 标志设为 1,带 Client 的 SN 序号(随机的,每 4ms 加 1),还带 MSS(最大数据块长度)。

  2. 第二次握手:Server 收到 SYN,进入 SYN_RCVD 状态,回个 SYN+ACK 帧。ACK 标志 1,确认序号是 Client 的 SN+1;SYN 标志 1,带 Server 的 SN 序号;也带 Server 的 MSS。

  3. 第三次握手:Client 收到 SYN+ACK,状态从 SYN_SENT 变成 ESTABLISHED(自己这边连接好了,能发数据了),然后发 ACK 帧给 Server。ACK 标志 1,确认序号是 Server 的 SN+1。有时候 Client 会把 ACK 和第一帧数据放一起发。

  4. Server 收到 ACK,状态从 SYN_RCVD 变成 ESTABLISHED,Server 这边也连接好了,能发数据了。TCP 全双工连接建好。

三次握手图解

图片

握手完,就开始传数据了。传完了就断连接,断连接得四次挥手。

TCP 的四次挥手

业务数据传完,TCP 开始断连接,两边都能主动发起,这过程用四次挥手。

四次挥手具体过程

  1. 第一次挥手:主动断开方(客户端或服务器)发 FIN 结束请求,FIN 位设 1,正确设序号和确认号。发完进入 FIN_WAIT_1 状态,意思是 “我没数据要发了,准备关连接”。

  2. 第二次挥手:被动断开方收到 FIN,发 ACK 响应,确认号是 FIN 的序号 + 1,意思是 “我知道你要关了”。然后进入 CLOSE-WAIT 状态,告诉上层应用 “对方那边关了,它没数据了,但我发数据它还收”。CLOSE-WAIT 会持续一会儿。主动断开方收到 ACK,从 FIN_WAIT_1 变成 FIN_WAIT_2。

  3. 第三次挥手:被动断开方发完剩余数据,或 CLOSE-WAIT 超时后,发 FIN+ACK,意思是 “我数据也发完了”,然后进入 LAST_ACK 状态。

  4. 第四次挥手:主动断开方收到 FIN+ACK,发最后一个 ACK,然后进入 TIME_WAIT 状态,等超时后关连接。TIME_WAIT 状态等 2MSL,期间没收到其他报文,就证明对方关好了,自己也关。被动断开方收到最后 ACK,直接关连接。

四次挥手图解

图片

主动断开方在 TIME_WAIT 状态等 2MSL,为啥?

2MSL 是两倍的 MSL(一个 TCP 报文在网络里的最大存活时间)。一来确保双方都关好:要是最后 ACK 丢了,被动方会重发 FIN+ACK,主动方在 2MSL 内收到,会重发 ACK,再等 2MSL,保证被动方收到。二来防止旧连接的失效报文出现在新连接里:等 2MSL,旧报文都消失了,新连接就不会受影响。

MSL 的时间,RFC1122 推荐 2 分钟,LwIP 协议栈默认 1 分钟,Berkeley 的默认 30 秒,一般 1-4 分钟。

三次握手、四次挥手,一次 TCP 连接至少通信 7 次,成本不低啊。

三次握手、四次挥手的常见面试题

这些问题面试常考,是重点也是难点:

问题(1):为啥断连接要四次挥手,建连接只要三次握手?

断连接时,被动方收到 FIN,可能还有数据没发完,不能马上关,只能先回个 ACK,等数据发完再发 FIN,所以得拆成两步,共四次。

建连接时,Server 收到 SYN,ACK(应答)和 SYN(自己也开连接)之间没啥数据要发,能合并成一个 SYN+ACK,所以三次就行。

问题(2):建连接为啥是三次握手,能改成两次吗?

三次握手有俩作用:一是双方都做好发数据的准备,且知道对方准备好了;二是协商初始 SN 序号。

改成两次的话,可能死锁。假设两次握手:Client 发 SYN,Server 回 SYN+ACK,Server 觉得连接建好了,开始发数据。要是 SYN+ACK 丢了,Client 以为没建好,会忽略 Server 发的数据,一直等;Server 没收到确认,超时重发,就死循环了。

问题(3):主动断开方在 TIME-WAIT 状态为啥要等 2MSL?

一是确保双方都关好:要是最后 ACK 丢了,被动方会重发 FIN+ACK,主动方在 2MSL 内收到,重发 ACK,再等 2MSL,保证被动方收到,顺利关闭。要是主动方发完 ACK 就关,就收不到重发的 FIN+ACK,被动方关不了。

二是防旧报文干扰新连接:等 2MSL,旧连接的报文都没了,新连接就不会有旧报文。

问题(4):建完连接,Client 突然挂了咋办?

TCP 有保活计时器。Server 每收到一次 Client 的数据,计时器就复位。超时时间一般 2 小时,2 小时没收到数据,Server 发探测报文,之后每隔 75 秒发一次,发 10 次还没反应,就认为 Client 挂了,关连接。觉得 2 小时太长,能自己调保活参数。

面试官:看你简历说精通TCP和IP,那我们来讨论下网络模型和TCP、IP协议,讲下你的理解先

面试官:看你画的图,TCP有自己的首部结构,这都有哪些字段,最好说说它们的作用

面试官:那TCP和UDP有什么区别

面试官:刚才你说TCP是可靠的连接,它是怎么实现的

面试官:具体说一说三次握手和四次挥手机制

面试官:如果没有三次握手会有什么问题呢

面试官:TIME_WAIT和CLOSE_WAIT的区别在哪

面试官:TIME_WAIT的作用呢,还有为啥状态时间要保持两个MSL

面试官:刚才你还有提到拥塞控制,TCP协议用什么方式去解决拥塞的

面试官:那拥塞控制还有其他什么方式呢

面试官:知道滑动窗口不,客户端和服务端控制滑动窗口的过程是怎样的

面试官:那你知道滑动窗口和拥塞窗口有什么区别不

面试官:TCP的粘包和拆包问题,你怎么看

面试官:那解决粘包和拆包的方法都有哪些?

面试官:SYN Flood了解吗

面试官:对TCP的掌握挺不错的,下面问下HTTP的知识。你知道一次HTTP请求,程序一般经历了哪几个步骤?

面试官:HTTP有哪几种响应状态码,列举几个你熟悉的

面试官:不错,再考考你,session和cookie有什么区别

面试官:不错,那你了解什么是HTTP分块传送吗

面试官:HTTP分块传送有什么好处

面试官:HTTP的长连接你怎么理解

面试官:HTTP是安全的吗?怎么做到安全的HTTP协议传输

面试官:HTTPS和HTTP的区别,你是怎么理解的

面试官:SSL/TLS是什么,HTTPS的安全性是怎样实现的?

粉丝福利, 免费领取C/C++ 开发学习资料包、技术视频/项目代码,1000道大厂面试题,内容包括(Qt,音视频开发,C++基础,数据库,高性能网络,组件设计,中间件开发,框架,分布式架构等进阶学习资料和大厂技术栈学习路线)↓↓↓↓↓↓见下面↓↓文章底部关注领取↓↓
 

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐