【计网】04.TCP三次握手四次挥手

【嵌入式八股】一、语言篇https://www.nowcoder.com/creation/manager/columnDetail/mwQPeM

【嵌入式八股】二、计算机基础篇(本专栏)https://www.nowcoder.com/creation/manager/columnDetail/Mg5Lym

【嵌入式八股】三、硬件篇https://www.nowcoder.com/creation/manager/columnDetail/MRVDlM

【嵌入式八股】四、嵌入式Linux篇https://www.nowcoder.com/creation/manager/columnDetail/MQ2bb0

传输层TCP/UDP

TCP三次握手四次挥手

66.TCP头部中有哪些信息?

TCP数据报格式(左图) UDP数据报格式也放这(右图),不具体解释了。 alt

结合三次握手四次挥手来看

  • 端口:

    区分应用层的不同应用进程

    扩展:应用程序的端口号和应用程序所在主机的 IP 地址统称为 socket(套接字),IP:端口号, 在互联网上 socket 唯一标识每一个应用程序,源端口+源IP+目的端口+目的IP称为”套接字对“,一对套接字就是一个连接,一个客户端与服务器之间的连接。 alt

  • 序号seq(32bit):

    传输方向上字节流的字节编号。用于 TCP 通信过程中某一传输方向上字节流的每个字节的编号,为了确保数据通信的有序性,避免网络中乱序的问题。接收端根据这个编号进行确认,保证分割的数据段在原始数据包的位置。初始时序号会被设置一个随机的初始值(ISN),之后每次发送数据时,序号值 = ISN + 数据在整个字节流中的偏移。假设A -> B且ISN = 1024,第一段数据512字节已经到B,则第二段数据发送时序号为1024 + 512。

  • 确认序号ack(32bit):

    确认序列号是接收确认端所期望收到的下一序列号。确认序号应当是上次已成功收到数据字节序号seq加1,只有当标志位中的 ACK 标志为 1 时该确认序列号的字段才有效。主要用来解决不丢包的问题。

  • 首部长(4bit):

    标识首部有多少个4字节 * 首部长,最大为15,即60字节。

  • 标志位(6bit):

    • URG:(urgent紧急) 标志紧急指针是否有效。
    • ACK:(acknowledgement 确认)标志确认号是否有效(确认报文段)。用于解决丢包问题。
    • PSH:(push传送) 提示接收端立即从缓冲读走数据。
    • RST:(reset重置) 表示要求对方重新建立连接(复位报文段)。
    • SYN:(synchronous同步) 表示请求建立一个连接(连接报文段)。
    • FIN:(finish结束) 表示关闭连接(断开报文段)。
  • 窗口(16bit):

    接收窗口,滑动窗口大小。用于告知对方(发送方)本方的缓冲还能接收多少字节数据。用于解决流控。

  • 校验和(16bit):

    接收端用CRC检验整个报文段有无损坏。

  • 紧急指针(16bit):

    紧急指针表示紧急数据的末尾位置,用于标识紧急数据的范围。

67.端口有效范围是多少到多少?

端口号的有效范围是从0到65535,其中0被保留,不能用于应用程序端口号。其中,0到1023是系统保留端口,一些常用的端口号也被规定为某些服务的默认端口号。例如,HTTP的默认端口号是80,HTTPS的默认端口号是443,SSH的默认端口号是22等。

1024到49151是注册端口范围,一些应用程序可以使用这些端口号,但并没有被正式分配给任何特定的服务。这些端口号通常被用于客户端程序和服务端程序之间的通信。

49152到65535是动态或私有端口范围,这些端口号可以由应用程序动态分配和使用,但不会被分配给任何特定的服务。这些端口号通常被用于客户端程序和服务端程序之间的通信。

68.一台机器能够使用的端口号上限是否可以修改?如果想要用的端口超过这个限制怎么办?

大多数操作系统默认允许使用的动态端口数量为几千个,但是可以通过修改系统内核参数来增加这个数量。不过,修改这些参数需要管理员权限和谨慎操作,否则可能会导致系统出现问题或安全漏洞。

如果需要使用的端口超过了机器的限制,一种常见的做法是使用负载均衡器或代理服务器。可以将请求发送到负载均衡器或代理服务器,再由它们转发到实际的服务端口,从而实现同时支持多个服务。

69.简述一下TCP建立连接和断开连接的过程。

三次握手 alt

TCP建立连接过程(三次握手):

  1. 客户端向服务端发送SYN包(SYN=1,ACK=0),表示请求建立连接,并指定客户端的初始序列号seq=x。客户端进入 SYN_SENT状态,等待Server确认。

  2. 服务端收到客户端的SYN=1知道Client请求建立连接,向客户端发送SYN/ACK包(SYN=1,ACK=1),表示同意建立连接,并指定服务端的初始序列号seq=y,同时确认客户端的序列号ack=x+1。服务端进入 SYN_RCVD状态。

  3. 客户端收到服务端的SYN/ACK包后,检查ack是否为x+1,ACK是否为1,如果正确则向服务端发送ACK包(SYN=0,ACK=1),确认建立连接,并指定确认序列号ack=y+1。服务端检查ack是否为y+1,ACK是否为1,如果正确则连接建立成功,客户端和服务端进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

四次挥手 alt

TCP断开连接过程(四次挥手):

  1. 客户端向服务端发送FIN包(FIN=1,ACK=1),表示请求断开连接,并指定序列号seq=x。客户端进入 FIN_WAIT_1状态,此时客户端依然可以接收服务器发送来的数据。

  2. 服务端收到客户端的FIN包后,向客户端发送ACK包(ACK=1),确认接收到了断开连接请求,并指定确认序列号ack=x+1。服务器进入CLOSE_WAIT 状态。客户端收到后进入FIN_WAIT_2状态。

  3. 当服务器没有数据要发送时,发送FIN包(FIN=1,ACK=1),请求断开连接,并指定序列号seq=y。此时服务器进入LAST_ACK状态,等待客户端的确认。

  4. 客户端收到服务端的FIN包后,向服务端发送ACK包(ACK=1),确认接收到了断开连接请求,并指定确认序列号ack=y+1。此时客户端进入TIME_WAIT状态,等待2MSL(MSL:报文段最大生存时间),然后关闭连接。

完整过程 alt

70.常见TCP的连接状态有哪些?

请你说一说TCP的模型,状态转移。

  • CLOSED:初始状态。

  • LISTEN:服务器处于监听状态。

  • SYN_SEND:客户端socket执行CONNECT连接,发送SYN包,进入此状态。

  • SYN_RECV:服务端收到SYN包并发送服务端SYN包,进入此状态。

  • ESTABLISH:表示连接建立。客户端发送了最后一个ACK包后进入此状态,服务端接收到ACK包后进入此状态。

  • FIN_WAIT_1:终止连接的一方(通常是客户机)发送了FIN报文后进入。等待对方FIN。

  • CLOSE_WAIT:(假设服务器)接收到客户机FIN包之后等待关闭的阶段。在接收到对方的FIN包之后,自然是需要立即回复ACK包的,表示已经知道断开请求。但是本方是否立即断开连接(发送FIN包)取决于是否还有剩余数据需要发送给客户端,若有,则在发送FIN包之前均为此状态。

  • FIN_WAIT_2:此时是半连接状态,即有一方要求关闭连接,等待另一方关闭。发送断开请求一方还有接收数据能力,但已经没有发送数据能力。客户端接收到服务器的ACK包,但并没有立即接收到服务端的FIN包,进入FIN_WAIT_2状态。

  • LAST_ACK:服务端发动最后的FIN包,等待最后的客户端ACK响应,进入此状态。

  • TIME_WAIT:客户端收到服务端的FIN包,并立即发出ACK包做最后的确认,在此之后的2MSL时间称为TIME_WAIT状态。在2MSL时间内,同一个socket不能再被使用,否则有可能会和旧连接数据混淆(如果新连接和旧连接的socket相同的话)。

    如果客户端直接进入CLOSED状态,如果服务端没有接收到最后一次ACK包会在超时之后重新再发FIN包,此时因为客户端已经CLOSED,服务端就不会收到ACK而是收到RST。所以TIME_WAIT状态是防止最后一次握手数据没有到达对方而触发重传FIN准备的。

关发接建,1关2最

71.TCP的三次握手和四次挥手的原因是什么?

为什么TCP建立连接是三次握手,而关闭连接却是四次挥手?

为什么是三次握手?

  1. 三次握手才可以阻止重复历史连接的初始化(主因)
  2. 三次握手才可以同步双方的初始序列号
  3. 三次握手才可以避免资源浪费

解释: 1、阻止重复历史连接的初始化(主因)

为了防止已失效的连接请求报文段突然有送到了B,而产生错误

假设两次握手时,A发出的第一个请求连接报文段在某一网络节点长时间滞留,以致延误到连接释放后才到达B。B收到失效的连接请求报文段后,认为是A又发出一次新的连接请求。于是向A发送确认报文段,同意建立连接,此时在假定两次握手的前提下,连接建立成功。这样会导致B的资源白白浪费。

如果已失效的连接请求报文段突然又送到了服务端

  1. 当旧的SYN报文先到达服务端时,服务端回⼀个ACK+SYN报文。

  2. 客户端收到后可以根据自身的上下文,判断这是⼀个历史连接(序列号过期或超时),那么客户端就会发送RST 报文给服务端,表示中止这一次连接。

    两次握手在收到服务端的响应后开始发生数据,不能判断当前连接是否是历史连接。 三次握手可以在客户端准备发送第三次报文时,客户端因有足够的上下文来判断当前连接是否是历史连接。

2、同步双方的初始序列号 TCP 协议的通信双方, 都必须维护⼀个「序列号」 , 序列号是可靠传输的⼀个关键因素。

  • 接收端可以去除重复数据。

  • 接收端可以按照序列号顺序接收。

  • 标识发送的数据包,哪些已经被收到。

    两次握手只保证了一方的初始序列号能被对方成功接收,没办法保证双方的初始序列号都能被确认接收。

    三次握手一来一回,才能确保双方的初始序列号能被可靠的同步。

3、避免资源浪费。

  1. 两次握手会造成消息滞留情况下,服务器重复接受无用的连接请求 SYN 报文,而造成重复分配资源。

  2. 只有两次握手时,如果客户端的SYN请求连接在网络中阻塞,客户端没有收到服务端的ACK报文,会重新发送SYN。

  3. 由于没有第三次握手,服务器不清楚客户端是否收到了自己发送的建立连接的 ACK 确认信号,所以每收到一个 SYN 就只能先主动建立个连接。

为什么是四次挥手?

  • TCP协议是全双工通信,这意味着客户端和服务器端都可以向彼此发送数据,所以关闭连接是双方都需要确认的共同行为

  • 服务端通常需要等待完成数据的发送和处理, 所以服务端的ACK和FIN⼀般都会分开发送,从而比三次握手导致多了⼀次。

    关闭连接时,客户端发送FIN报文,表示其不再发送数据, 但还可以接收数据。

    服务端收到FIN报文,先回一个ACK应答报文,服务端可能还要数据需要处理和发送,等到其不再发送数据时,才发送FIN报文给客户端表示同意关闭连接。

  • 如果采用三次挥手来关闭连接,可能会出现以下问题:

    • 客户端发送FIN报文后,服务端无法确认客户端是否真的已经关闭了连接,因此需要等待一段时间才能确认客户端已经关闭连接。
    • 服务端发送FIN报文后,

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

查阅整理上千份嵌入式面经,将相关资料汇集于此,主要包括: 0.简历面试 1.语言篇 2.计算机基础【本专栏】 3.硬件篇 4.嵌入式Linux (建议PC端查看)

全部评论

相关推荐

2025-12-18 11:59
广州南方学院 C++
牛客78682892...:直接点还好,总比要了简历也不回的强
点赞 评论 收藏
分享
评论
4
13
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务