【计网】TCP 协议详解 与 常见面试题

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

不用死记,只需要清楚三次握手,四次挥手的流程,回答的时候心里要记住,假设网络是不可靠的

问题(1):为什么关闭连接时需要四次挥手,而建立连接却只要三次握手?

关闭连接时,被动断开方在收到对方的FIN结束请求报文时很可能没有发送完业务数据,并不能立即关闭连接,被动方只能先回复一个ACK响应报文,告诉主动断开方:​"你发的FIN报文我收到了,只有等到我所有的业务报文都发送完了,我才能真正结束,在结束之前,我会发给你FIN+ACK报文的,你先等着"​。所以,被动断开方的确认报文需要拆成两步,故总共需要四次挥手。

在建立连接场景中,Server的应答可以稍微简单一些。当Server收到Client的SYN连接请求报文后,其中ACK报文表示对请求报文的应答,SYN报文表示服务端的连接也已经同步开启了,而ACK报文和SYN报文之间不会有其他报文需要发送,故而可以合二为一,可以直接发送一个SYN+ACK报文。所以,在建立连接时,只需要三次握手即可。

问题(2):为什么连接建立的时候是三次握手,可以改成两次握手吗?

三次握手完成两个重要的功能:一是双方都做好发送数据的准备工作,而且双方都知道对方已准备好;二是双方完成初始SN序列号的协商,双方的SN序列号在握手过程中被发送和确认。如果把三次握手改成两次握手,可能发生死锁。两次握手的话,缺失了Client的二次确认ACK帧,假想的TCP建立连接时的二次挥手可以如图所示。

在假想的TCP建立连接时的二次握手过程中,Client给Server发送一个SYN请求帧,Server收到后发送确认应答SYN+ACK帧。按照两次握手的协定,Server认为连接已经成功地建立,可以开始发送数据帧。在这个过程中,如果确认应答SYN+ACK帧在传输中被丢失,Client没有收到,Client将不知道Server是否已准备好,也不知道Server的SN序列号,Client认为连接还未建立成功,将忽略Server发来的任何数据分组,会一直等待Server的SYN+ACK确认应答帧。Server在发出的数据帧后,一直没有收到对应的ACK确认后就会产生超时,重复发送同样的数据帧。这样就形成了死锁。

问题(3):为什么主动断开方在TIME-WAIT状态必须等待2MSL?

原因之一:主动断开方等待2MSL的时间是为了确保两端都能最终关闭。假设网络是不可靠的,被动断开方发送FIN+ACK报文后,其主动方的ACK响应报文有可能丢失,这时的被动断开方处于LAST-ACK状态,由于收不到ACK确认被动方一直不能正常地进入CLOSED状态。在这种场景下,被动断开方会超时重传FIN+ACK断开响应报文,如果主动断开方在2MSL时间内收到这个重传的FIN+ACK报文,就会重传一次ACK报文,然后再一次重新启动2MSL计时等待,这样就能确保被动断开方能收到ACK报文,从而能确保被动方顺利进入CLOSED状态。只有这样,双方才都能够确保关闭。反过来说,如果主动断开方在发送完ACK响应报文后不是进入TIME_WAIT状态去等待2MSL时间,而是立即释放连接,则将无法收到被动方重传的FIN+ACK报文,所以不会再发送一次ACK确认报文,此时处于LAST-ACK状态的被动断开方无法正常进入CLOSED状态。

原因之二:防止"旧连接已失效的数据报文"出现在新连接中。主动断开方在发送完最后一个ACK报文后再经过2MSL才能最终关闭和释放端口。这就意味着,相同端口的新TCP新连接需要在2MSL的时间之后才能够正常建立。2MSL这段时间内,旧连接所产生的所有数据报文都已经从网络中消失了,从而确保下一个新的连接中不会出现这种旧连接请求报文。

问题(4):如果已经建立了连接,但是Client端突然出现故障了怎么办?

TCP还设有一个保活计时器,Client如果出现故障,Server不能一直等下去,这样会浪费系统资源。每收到一次Client的数据帧后,Server的保活计时器都会复位。计时器的超时时间通常设置为2小时,若2小时还没有收到Client的任何数据帧,Server就会发送一个探测报文段,以后每隔75秒发送一次。若一连发送10个探测报文仍然没有反应,Server就认为Client出了故障,接着关闭连接。如果觉得保活计时器的两个多小时的间隔太长,可以自行调整TCP连接的保活参数。

OSI、TCP/IP模型

国际标准化组织ISO为了使网络应用更为普及,推出了OSI参考模型,即开放式系统互联(Open System Interconnect)模型,一般都叫OSI参考模型。OSI参考模型是ISO组织在1985年发布的网络互连模型,其含义就是为所有公司使用一个统一的规范来控制网络,这样所有公司遵循相同的通信规范,网络就能互联互通了。

OSI模型定义了网络互连的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层)​,每一层实现各自的功能和协议,并完成与相邻层的接口通信。

下面是常见的协议

TCP/IP协议是互联网最基本的协议,在一定程度上参考了七层ISO模型,有些复杂,所以在TCP/IP协议中七层被简化为四个层次。TCP/IP模型中的各种协议依功能不同被归属到四层之中,常被视为简化后的七层OSI模型

TCP/IP 应用层

应用层包括所有和应用程序协同工作并利用基础网络交换应用程序的业务数据的协议。一些特定的程序被认为运行在这个层上,该层协议所提供的服务能直接支持用户应用。应用层协议包括HTTP(万维网服务)​、FTP(文件传输)​、SMTP(电子邮件)​、SSH(安全远程登录)​、DNS(域名解析)以及许多其他协议。

TCP/IP 传输层

传输层的协议解决了端到端可靠性等问题,能确保数据可靠地到达目的地,甚至能保证数据按照正确的顺序到达目的地。传输层的主要功能大致如下:

(1)为端到端连接提供传输服务。

(2)这种传输服务分为可靠和不可靠的,其中TCP是典型的可靠传输UDP是不可靠传输

(3)为端到端连接提供流量控制差错控制服务质量(Quality of Service, QoS)等管理服务。

传输层主要有两个性质不同的协议:TCP(传输控制协议)和UDP(用户数据报协议)​。

TCP是一个面向连接的、可靠的传输协议,提供一种可靠的字节流,能保证数据完整、无损并且按序到达。TCP尽量连续不断地测试网络的负载并且控制发送数据的速度以避免网络过载。另外,TCP试图将数据按照规定的顺序发送。

UDP是一个无连接的数据报协议,是一个"尽力传递"和"不可靠"协议,不会对数据包是否已经到达目的地进行检查,并且不保证数据包按顺序到达。

TCP/IP协议的网络层

TCP/IP协议网络层的作用是在复杂的网络环境中为要发送的数据报找到一个合适的路径进行传输。简单来说,网络层负责将数据传输到目标地址,目标地址可以是多个网络通过路由器连接而成的某一个地址。另外,网络层负责寻找合适的路径到达对方计算机,并把数据帧传送给对方,网络层还可以实现拥塞控制、网际互联等功能。网络层协议的代表包括ICMP、IP、IGMP等。

TCP/IP协议的链路层

链路层有时也称作数据链路层或网络接口层,用来处理连接网络的硬件部分。该层既包括操作系统硬件的设备驱动、NIC(网卡)​、光纤等物理可见部分,也包括连接器等一切传输媒介。在这一层中,数据的传输单位为比特。其主要协议有ARP、RARP等。

HTTP报文传输原理

利用TCP/IP进行网络通信时,数据包会按照分层顺序与对方进行通信。发送端从应用层往下走,接收端从链路层往上走。从客户端到服务器的数据,每一帧的传输顺序都为应用层→传输层→网络层→链路层→链路层→网络层→传输层→应用层。

在数据封装时,数据经过每个层都会打上该层特定标识,添加上头部。

TCP/IP除了与OSI在分层模块上稍有区别外,更重要的区别是:OSI参考模型注重"通信协议必要的功能是什么"​,而TCP/IP则更强调"在计算机上实现协议应该开发哪种程序"​。

OSI更像是一位通信系统架构师,考虑的是"为了完成端到端通信,从理论上需要哪些功能模块

TCP/IP更像是一位软件工程师,考虑的是"要开发什么样的程序才能让计算机实现网络通信

实际上,在传输过程中,数据报文会在不同的物理网络之间传递。还是以一个HTTP请求的传输为例,请求在不同物理网络之间的传输过程大致如图

TCP 协议

报文格式

在TCP/IP协议栈中,IP层只关心如何使数据能够跨越本地网络边界的问题,而不关心数据如何传输 。TCP/IP协议栈配合起来解决数据如何通过许许多多个点对点通路顺利传输到目的地。一个点对点通路被称为一"跳"(hop),通过TCP/IP协议栈,网络成员能够在许多"跳"的基础上建立相互的数据通路。

一个传输层TCP的数据帧大致包含以下字段:

1. 源端口号 (Source Port)

  • 占16位,表示报文的发送端口
  • 源端口号与源IP地址组合,共同标识报文的发送地址
  • 作用:标识数据来源的应用程序

2. 目的端口号 (Destination Port)

  • 占16位,表示报文的接收端口
  • 目的端口号与目的IP地址组合,共同标识报文的接收地址
  • 重要概念:TCP连接由四元组唯一确定:"源端口号+源IP"与"目的端口号+目的IP"

3. 序号 (Sequence Number, SN)

  • 占32位,用于标识发送的数据字节流位置

  • 序号的含义取决于SYN控制标志的值:

    • 当SYN=1时:表示连接建立阶段,序号为初始序号ISN(Initial Sequence Number),通过算法随机生成
    • 当SYN=0时 :在正常数据传输阶段
      • 第一个报文序号为ISN+1
      • 后续报文序号 = 前一个报文的SN值 + 前一个报文的净荷字节数
  • 序号计算示例

    • 若发送的TCP帧净荷为12字节,序号为5
    • 则下一个数据包的序号应为:5 + 12 = 17
  • 序号的作用

    • 发送端跟踪已发送的数据量
    • 接收端识别重复包并丢弃
    • 对乱序数据包进行重排序
    • 为上层提供有序的数据流

4. 确认序号 (Acknowledgment Number, ACK)

  • 占32位,标识报文接收端期望接收的下一个字节序列号
  • 仅当ACK控制位设置时有效
  • 确认序号指向的是接收端下一个期望接收的数据包序列号
  • 表示接收端已成功接收了序号小于确认序号的所有字节

这四个字段共同构成了TCP可靠传输的基础,确保了数据传输的有序性和可靠性。

举个例子,假设发送端(如Client)发送3个净荷为1000B、起始SN序号为1的数据包给服务端,服务端每收到一个包之后,需要回复一个ACK响应确认数据包给客户端。ACK响应数据包的ACK Number值为每个客户端包的SN+包净荷,除了表示服务端已经确认收到的字节数,还表示期望接收到的下一个客户端发送包的SN序号。具体的ACK值如图10-9左边的正常传输部分所示。

服务端第1个ACK包的ACK Number值为1001,是通过客户端第1个包的SN+包净荷(1+1000)计算得到,表示期望第2个客户端包的SN序号为1001;服务端第2个ACK包的ACK Number值为2001,为客户端第2个包的SN+包净荷(2000+1),表示期望第3个服务端包的SN为2001,以此类推。

如果发生错误,假设服务端在处理客户端的第二个发送包时发生异常,服务端仍然回复一个ACK Number值为1001的确认包,则客户端的第二个数据包需要重复发送,具体的ACK值如图右边的正常传输部分所示。

只有控制标志的ACK标志为1时,数据帧中的确认序号ACK Number才有效。TCP规定,连接建立后,所有发送报文的ACK必须为1,即建立连接后所有报文的确认序号有效。如果是SYN类型的报文,其ACK标志为0,故没有确认序号。

5.控制标志

控制标志(Control Bits)共6位,具体的标志位为URG、ACK、PSH、RST、SYN、FIN,如表所示

在连接建立的三次握手过程中,若只是单个SYN置位,则表示的是建立连接请求。如果SYN和ACK同时置位为1,就表示建立连接之后的响应。

5.窗口

长度为16位,共2字节,用来进行流量控制。流量控制的单位为字节数,这个值是本端期望一次接收的字节数。

总体来说,TCP的可靠性主要通过以下几点来保障:

① 应用数据分割成TCP认为最适合发送的数据块。这部分是通过MSS(最大数据包长度)选项来控制的,通常被称为一种协商机制。MSS规定了TCP传往另一端的最大数据块的长度。值得注意的是,MSS只能出现在SYN报文段中,若一方不接收来自另一方的MSS值,则MSS就定为536字节。一般MSS值越大越好,以提高网络的利用率。

② 重传机制。设置定时器,等待确认包,如果定时器超时还没有收到确认包,则报文重传。

③ 对首部和数据进行校验。

④ 接收端对收到的数据进行排序,然后交给应用层。

⑤ 接收端丢弃重复的数据。

⑥ 提供流量控制,主要是通过滑动窗口来实现的。

三次握手

TCP连接建立时,双方需要经过三次握手,具体过程如下:

第一次握手

Client进入SYN_SENT状态,发送一个SYN帧来主动打开传输通道,该帧的SYN标志位被设置为1,同时会带上Client分配好的SN序列号,该SN是根据时间产生的一个随机值,通常情况下每间隔4ms(毫秒)会加1。除此之外,SYN帧还会带一个MSS(最大报文段长度)可选项的值,表示客户端发送出去的最大数据块的长度。

第二次握手

Server在收到SYN帧之后,会进入SYN_RCVD状态,同时返回SYN+ACK帧给Client,主要目的在于通知Client"Server已经收到SYN消息,现在需要进行确认"​。Server发出的SYN+ACK帧的ACK标志位被设置为1,其确认序号AN(Acknowledgment Number)值被设置为Client的SN+1; SYN+ACK帧的SYN标志位被设置为1, SN值为Server生成的SN序号;SYN+ACK帧的MSS(最大报文段长度)表示的是Server的最大数据块长度。

第三次握手

Client在收到Server的第二次握手SYN+ACK确认帧之后,首先将自己的状态从SYN_SENT变成ESTABLISHED,表示自己方向的连接通道已经建立成功,Client可以发送数据给Server了。然后,Client发ACK帧给Server,该ACK帧的ACK标志位被设置为1,其确认序号AN(Acknowledgment Number)值被设置为Server的SN+1。还有一种情况,Client可能会将ACK帧和第一帧要发送的数据合并到一起发送给Server。

Server在收到Client的ACK帧之后会从SYN_RCVD状态进入ESTABLISHED状态。至此,Server方向的通道连接建立成功。Server可以发送数据给Client, TCP的全双工连接建立完成。

Client和Server完成了三次握手后,双方就进入数据传输阶段。数据传输完成后,连接将断开。连接断开的过程需要经历四次挥手。

四次挥手

第一次挥手

主动断开方(可以是客户端,也可以是服务端)​,向对方发送一个FIN结束请求报文,此报文的FIN位被设置为1,并且正确设置Sequence Number(序列号)和Acknowledgment Number(确认号)​。发送完成后,主动断开方进入FIN_WAIT_1状态,表示主动断开方没有业务数据要发送给对方,准备关闭Socket连接了。

第二次挥手

正常情况下,在收到了主动断开方发送的FIN断开请求报文后,被动断开方会发送一个ACK响应报文,报文的Acknowledgment Number(确认号)值为断开请求报文的Sequence Number(序列号)加1,该ACK确认报文的含义是:​"我同意你的连接断开请求"​。之后,被动断开方就进入了CLOSE-WAIT(关闭等待)状态,TCP服务会通知高层的应用进程,对方向本地方向的连接已经关闭,已经没有数据要发送了,若本地还要发送数据给对方,对方依然会接收。被动断开方的CLOSE-WAIT(关闭等待)还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

主动断开方在收到了ACK报文后,由FIN_WAIT_1转换成FIN_WAIT_2状态。

第三次挥手

在发送完成ACK报文后,被动断开方还可以继续完成业务数据的发送,待剩余数据发送完成或者CLOSE-WAIT(关闭等待)截止后,被动断开方会向主动断开方发送一个FIN+ACK结束响应报文,表示被动断开方的数据都发送完了,然后被动断开方进入LAST_ACK状态。

第四次挥手

主动断开方收到FIN+ACK断开响应报文后,还需要进行最后的确认,向被动断开方发送一个ACK确认报文,然后自己就进入TIME_WAIT状态,等待超时后最终关闭连接。处于TIME_WAIT状态的主动断开方在等待完成2MSL的时间后,如果期间没有收到其他报文,则证明对方已正常关闭,主动断开方的连接最终关闭。被动断开方在收到主动断开方的最后ACK报文以后,最终关闭连接,什么也不用管了。

处于TIME_WAIT状态的主动断开方在等待2MSL时间后才真正关闭连接通道。2MSL翻译过来就是两倍的MSL。MSL(Maximum Segment Lifetime)指的是一个TCP报文片段在网络中的最大存活时间,2MSL就是一次消息来回(一个发送和一个回复)所需的最大时间。如果直到2MSL主动断开方都没有再一次收到对方的报文(如FIN报文)​,则可以推断ACK已经被对方成功接收。此时,主动断开方将最终结束自己的TCP连接。所以,TCP的TIME_WAIT状态也称为2MSL等待状态。

相关推荐
XYN611 小时前
【嵌入式学习3】基于python的tcp客户端、服务器
服务器·开发语言·网络·笔记·python·学习·tcp/ip
the_nov1 小时前
20.IP协议
linux·服务器·网络·c++·tcp/ip
智想天开1 小时前
10.使用路由缓存提升性能
php
Lccee2 小时前
Windows安装 PHP 8 和mysql9,win下使用phpcustom安装php8.4.5和mysql9
开发语言·php
【云轩】3 小时前
《信使传奇:TCP与UDP的互联网使命》
网络协议·tcp/ip·udp
李恩泽的博客3 小时前
PHP时间处理
php
听风说雨的人儿5 小时前
浅谈在HTTP中GET与POST的区别
网络·网络协议·http
QC七哥5 小时前
一个简单的php加密的理解
php
JohnYan6 小时前
工作笔记 - PHP系统升级到7.4
linux·后端·php