【计算机网络专题】三次握手相关问题(必看题)

本问题对应的项目链接:高频题回答模版训练

PS:这个问的太多了,重点得理解吧,有时候具体细节忘了也没事的

1、说一下三次握手的大致过程?

2、为什么需要三次握手?2 次不可以吗?

3、第三次握手,可以携带数据吗?第二次呢?

4、三次握手连接阶段,最后一次ACK包丢失,会发生什么?

共以下 3 个回答

  • Everglow 永久会员 2023年11月4日 下午12:00
    1、说一下三次握手的大致过程?

    第一次握手:客户端主动请求连接,将tcp首部字段syn设为1,生成一个随机序列号表示客户端将从该字节序列开始发送消息,状态从closed – > syn-sent

    第二次握手:服务端收到syn报文后,将tcp首部字段syn,ack设为1,随机一个序列号表示服务器端将从该序列开始发送消息,并对客户端的syn进行确认具体表示就是syn seq + 1作为确认号,状态从listening -> syn received

    第三次握手:客户端收到syn ack报文后,对服务器的序列号进行确认,也就是seq + 1,状态从syn sent -> established,并且可以携带数据发送给服务器。

    服务端收到ack后就会从 syn received -> established

    2、为什么需要三次握手?2 次不可以吗?

    原因1: tcp是面向连接的可靠传输,所以连接双方要维护各自的序列号,和已收到的对方的序列号 来保证tcp段能够有序的无丢失无重复的被接收,所以为了正确的交换序列号需要四次握手,但可以把服务器的发送序列号和对客户端的确认合并成一次,所以三次就可以达到预期了。

    原因2: 提供一个中间状态,防止历史syn初始化连接。举例:客户端发送一个syn报文,但此时网络拥塞,并且客户端因为某种原因宕机重启,重启后,客户端仍想与服务器建立连接,再次发送syn,此时旧的syn报文到达客户端,在三次握手的情况下,服务器会回复一个syn ack但此时的状态为 syn received,客户端收到了该syn ack发现确认号和预期不一致,便会发送一个rst 报文表示连接终止。如果是两次握手,在服务器收到历史syn时,就会建立连接,为该连接分配资源并可以向客户端发送数据。即使之后客户端会发送rst来终止该连接,但还是浪费掉了服务器的资源。

    3、第三次握手,可以携带数据吗?第二次呢?

    第三次可以,因为客户端收到synack 就进入了 established状态,可以向服务器发送数据,第二次握手服务器仍处于syn received阶段,还未建立好连接,所以携带不了数据

    4、三次握手连接阶段,最后一次ACK包丢失,会发生什么?

    最后一次ack如果丢失,服务器无法判断是第二次握手丢失,还是第三次握手丢失,那么根据tcp的超时重传机制,服务器就会重新发送syn ack,如果达到了最大重传次数就会断开连接

    0 赞同 0 条回复
  • 秊 永久会员 2023年9月14日 下午6:14

    1、说一下三次握手的大致过程?

    客户端在与服务器建立 TCP 连接时首先会进行三次握手。下面分别介绍一下:

    第一次握手:客户端给服务端发送一个 SYN 报文,并指明客户端的初始化序列号 ISN,此时客户端处于 SYN_SEND 状态。

    第二次握手:服务器收到客户端的 SYN 报文后,会以自己的 SYN 报文作为应答,同时也指定了自己的 ISN,并把客户端发来的 ISN + 1 作为 ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_RCVD 状态。

    第三次握手,客户端收到 SYN 报文后,会将服务器发来的 ISN + 1 作为 ACK 报文发出,表示已经收到了服务端的 SYN 报文,此时客户端处于 ESTABLISHED 状态。

    最后服务器收到 ACK 报文之后,也会处于 ESTABLISHED 状态,到这里,双方的连接就建立好了。

    2、为什么需要三次握手?2 次不可以吗?

    RFC 文档中提到的有,三次握手的首要原因是防止旧的重复连接初始化造成混乱。可以考虑这样一个场景,客户端第一次握手时对服务端发送的 SYN 报文由于网络原因阻塞了,导致服务端没有接收到。接着客户端重启后,又重新向服务端发送一个新的 SYN 报文来请求建立链接。但是,有可能客户端第一次发送的旧 SYN 比新发的先到达,那么服务端根据这个旧 SYN 值 + 1 返回的 ACK 值就不是现在客户端期望接受到的,因为当前客户端重新发送了 SYN,希望收到的是新 SYN + 1 这个 ACK 的值,这样就避免了“旧 SYN 报文”初始化了连接,本质上是利用第二次握手时,服务端返回的 ACK 值作为一种中间状态来阻止历史连接。

    如果只握手两次的话,第二次握手之后服务端就进入了 ESTABLISHED 状态,此时服务端返回给客户端的信息是带有数据的,尽管等客户端收到 ACK 报文时,能够识别到这个是历史连接后会摒弃这个连接,也就是发送 RST 报文来断开连接,但服务端已经建立了这个历史连接,还白白发送了数据,浪费掉了服务端的资源。

    3、第三次握手,可以携带数据吗?第二次呢?

    这个问题 RFC 文档中提到过,第三次握手时,客户端向服务端返回的报文中可以携带数据,即使此时服务端是 SYN_REVEIVED 状态,但由于数据报中也带有 ACK 的值,服务端接受之后会先确认这个 ACK,然后建立连接,进入 ESTABLISHED 状态,之后就能正常接受这个数据包了。

    但需要多注意的是,一般情况下第三次握手的报文中是不会携带数据的,大多数情况都是客户端在发生第三次握手的报文之后,不等服务端先接受,就接着发送正常通信的数据包。服务端先接受到第三次握手包之后建立连接,接着正常接受数据包。但假如由于网络原因,客户端发送的第三次握手包丢失了,但接着发送的数据包正常被服务端接收,由于这个数据包中也带有 ACK 的值,服务端就会把这个数据包当作第三次握手包,先建立连接再正常读取数据。至于真正的第三次握手包,如果是丢失了的话就丢失吧,没影响。如果由于网络原因而比数据包后到达,服务端会直接忽略。

    TCP 的第一二次握手,都是不可以携带数据的。第一次握手不能的原因是防止恶意的握手请求。第二次不能是因为此时服务端只确认了客户端的“发送能力”正常,却不知道接受能力是否正常,所以还不能携带数据。

    4、三次握手连接阶段,最后一次ACK包丢失,会发生什么?

    这个需要分情况看,第三次握手的 ACK 包丢失后,客户端有没有继续发送带有 ACK 的数据包,如果有,还是可以建立连接的。如果没有,也就是服务端此时迟迟接收不到来自客户端的 ACK,那么站在服务端的视角,有可能是第二次握手时给客户端的 SYN + ACK 丢失,也有可能是客户端第三次握手的 ACK 丢失。不管哪种情况,服务端此时只需重新进行第二次握手,也就是发送给客户端一份新的 SYN + ACK 即可,客户端收到后也会重新发送一份 ACK 报文,建立连接。

    0 赞同 0 条回复
  • 小肸 永久会员 2023年8月28日 下午6:24

    第一次握手:客户端生成一个随机数放入TCP头部的序列号中,作为客户端的初始序列号,并将SYN位置为1,然后将SYN报文发送给服务端。此时客户端进入SYN_SENT状态。
    第二次握手:服务端收到SYN报文后,取出客户端的初始化序列号,然后将值+1放入TCP头部的确认应答号,然后生成一个随机数放入序列号中,作为服务端的初始化序列号,并将SYN和ACK位置为1,最后将SYN+ACK报文发送给客户端,服务端进入SYN_RCVD状态。
    第三次握手:客户端收到SYN+ACK报文后进入established状态,此时客户端可以确保自身以及服务端的数据接受和发送能力没有问题,TCP连接已经建立,所以客户端可以向服务端发送数据,第三次握手可以携带数据。客户端取出服务端的初始化序列号的值,将值+1放入TCP头部的确认应答号,并将ACK位置为1,然后发送ACK报文给服务端。服务端接收到ACK报文后进入established状态,此时服务端和客户端双方已经建立起TCP连接。

    两次握手可能会造成历史连接覆盖了新连接,假如客户端发起建立TCP连接的SYN报文,因为网络拥塞导致迟迟没有达到服务端,客户端重新发送一个新的SYN报文给服务端,在服务端收到新的SYN报文后,旧的SYN报文也到达服务端。如果是三次握手,服务端会进入到SYN_RCVD这一个中间状态,然后发送SYN+ACK报文给客户端,客户端发现确认应答号错误,会发生RST报文告诉服务端释放连接,重新进行三次握手。如果是两次握手,服务端没有中间状态保存,直接进入established状态,此时对于服务端而言,TCP连接已经建立,可以发送数据,导致服务端的确认应答号和客户端的序列号不一致问题出现,然后客户端还要发送RST报文给服务端,服务端可能就是需要断开连接并且进行了白白地发送数据操作。总的来说,就是三次握手中服务端有一个中间状态可以防止旧的SYN报文比新的SYN报文晚到这种情况导致服务端建立无用的TCP连接。

    第二次握手不可以携带数据,因为服务端只知道客户端的发送数据能力正常,却不知道接受数据能力是否正常,因为服务端只收到了客户端的SYN报文,还没有收到ACK报文,所以不能携带数据。而第三次握手可以,在第三次握手时,客户端收到服务端的SYN+ACK报文,通过ACK报文可以知道服务端正常接收到第一次握手时的SYN报文,通过SYN+ACK报文可以知道服务端的发送和接受能力没有问题,所以第三次握手可以携带数据。

    服务端重传SYN+ACK报文。对于客户端而言,第三次握手的ACK包丢失客户端无法知晓,因为客户端是收到了服务端的SYN+ACK报文才会发送ACK报文进行第三次握手,所以服务端在发送第二次握手的SYN+ACK包后知道需要收到客户端的ACK包,如果迟迟没有收到,可能是因为第二次握手的SYN+ACK包丢失或者是第三次的ACK包丢失,服务端就需要重传SYN+ACK包,然后客户端收到SYN+ACK包后也相当于重传一次ACK包给服务端建立连接。

    0 赞同 0 条回复

# 回答此问题

后才能回答