【计算机网络面试】tcp/ip协议三次握手、四次挥手

TCP报文格式

TCP 报文是 TCP 层传输的数据单元,也称为报文段。TCP 报文中每个字段如图所示。
在这里插入图片描述
上图中 TCP 报文中每个字段的含义如下:

源端口和目的端口字段

  • TCP源端口(Source Port):源计算机上的应用程序的端口号,占 16 位。
  • TCP目的端口(Destination Port):目标计算机的应用程序端口号,占 16 位。

序列号字段
CP序列号(Sequence Number):占 32 位。它表示本报文段所发送数据的第一个字节的编号。在 TCP 连接中,所传送的字节流的每一个字节都会按顺序编号。当SYN标记不为1时,这是当前数据分段第一个字母的序列号;如果SYN的值是1时,这个字段的值就是初始序列值(ISN),用于对序列号进行同步。这时,第一个字节的序列号比这个字段的值大1,也就是ISN加1。

确认号字段
TCP 确认号(Acknowledgment Number,ACK Number):占 32 位。它表示接收方期望收到发送方下一个报文段的第一个字节数据的编号。其值是接收计算机即将接收到的下一个序列号,也就是下一个接收到的字节的序列号加1。

数据偏移字段
TCP 首部长度(Header Length):数据偏移是指数据段中的“数据”部分起始处距离 TCP 数据段起始处的字节偏移量,占 4 位。其实这里的“数据偏移”也是在确定 TCP 数据段头部分的长度,告诉接收端的应用程序,数据从何处开始。

保留字段
保留(Reserved):占 4 位。为 TCP 将来的发展预留空间,目前必须全部为 0。

标志位字段

  • CWR(Congestion Window Reduce):拥塞窗口减少标志,用来表明它接收到了设置 ECE 标志的 TCP 包。并且,发送方收到消息之后,通过减小发送窗口的大小来降低发送速率。
  • ECE(ECN Echo):用来在 TCP 三次握手时表明一个 TCP 端是具备 ECN 功能的。在数据传输过程中,它也用来表明接收到的 TCP 包的 IP 头部的 ECN 被设置为 11,即网络线路拥堵。
  • URG(Urgent):表示本报文段中发送的数据是否包含紧急数据。URG=1 时表示有紧急数据。当 URG=1 时,后面的紧急指针字段才有效。
  • ACK:表示前面的确认号字段是否有效。ACK=1 时表示有效。只有当 ACK=1 时,前面的确认号字段才有效。TCP 规定,连接建立后,ACK 必须为 1。
  • PSH(Push):告诉对方收到该报文段后是否立即把数据推送给上层。如果值为 1,表示应当立即把数据提交给上层,而不是缓存起来。
  • RST:表示是否重置连接。如果 RST=1,说明 TCP 连接出现了严重错误(如主机崩溃),必须释放连接,然后再重新建立连接。
  • SYN:在建立连接时使用,用来同步序号。当 SYN=1,ACK=0 时,表示这是一个请求建立连接的报文段;当 SYN=1,ACK=1 时,表示对方同意建立连接。SYN=1 时,说明这是一个请求建立连接或同意建立连接的报文。只有在前两次握手中 SYN 才为 1。
  • FIN:标记数据是否发送完毕。如果 FIN=1,表示数据已经发送完成,可以释放连接。

窗口大小字段
窗口大小(Window Size):占 16 位。它表示从 Ack Number 开始还可以接收多少字节的数据量,也表示当前接收端的接收窗口还有多少剩余空间。该字段可以用于 TCP 的流量控制。

TCP 校验和字段
校验位(TCP Checksum):占 16 位。它用于确认传输的数据是否有损坏。发送端基于数据内容校验生成一个数值,接收端根据接收的数据校验生成一个值。两个值必须相同,才能证明数据是有效的。如果两个值不同,则丢掉这个数据包。Checksum 是根据伪头 + TCP 头 + TCP 数据三部分进行计算的。

紧急指针字段
紧急指针(Urgent Pointer):仅当前面的 URG 控制位为 1 时才有意义。它指出本数据段中为紧急数据的字节数,占 16 位。当所有紧急数据处理完后,TCP 就会告诉应用程序恢复到正常操作。即使当前窗口大小为 0,也是可以发送紧急数据的,因为紧急数据无须缓存。

可选项字段
选项(Option):长度不定,但长度必须是 32bits 的整数倍。

三次握手

在这里插入图片描述

首先第一次握手是客户端发起的,客户端要给服务端发起一个建立连接的请求,建立连接的请求里面有一个标志位,这个标志位如果为1就代表建立连接即SNY位,它发的这个数据报文里面SNY位一定是1,说明这个连接建立了,同时还要生成随机的32位序列号 Initial seq number(初始化的序列号),为了简单我们将其标记为10000。有了这两个东西我们报文里面如果SNY位是1,seq=10000,当然第一次建立连接的时候是没有数据的,它只有报头相关的数据。服务端向客户端回一个SYN=1,也随机生成一个32位序列号,比如说是20000。这个seq其实起了很大的作用,比如说客户端给服务端发送报文,seq从10000开始,10001,10002…这样慢慢发,如果客户端发了个消息是900,那说明这个报文一定不合法,直接就把它扔掉。当然在服务端给客户端的应答里面还有一个ACK=1,代表你给我发了一个消息,我可以确认消息是有效的,同时要带上一个消息确认序号ack,ack包是seq+1,服务端就告诉客户端接下来你给我发送的报文需要从10001开始,接着往后发。两次连接建立以后,首先对于客户端而言,客户端给服务端发送信息,并且服务端回我,有了这两个信息,客户端就知道了我给客户端发信息,客户端能收到,同时我还能收到客户端的信息,两次信息以后客户端就笑了,我这边没问题。那么对于服务端可以吗?我们的第一次请求是客户端给服务端发送的,服务端收到,说明服务端接收客户端消息没问题,但是服务端发给客户端的消息,客户端一定能收到吗?服务端还是不知道,为了安全、可靠(客户端要知道我能连上服务端,服务端也能连上我;服务端也要知道客户端能连上我,我也能连上客户端)显然,两次握手达不到这个目的。服务端只是知道我能收到客户端的信息,但是客户端能不能收到我的信息,还是不知道。所以还需要再来一趟。客户端收到服务端的消息以后,他要立马给服务端一个消息,ACK=1,生成一个消息确认包ack=20001。
经过这一来二往三次握手,保证了客户端和服务端知道通信两方面都能进行。

四次挥手

在这里插入图片描述

客户端想要断开连接,报文里面的FIN位一定位1,再来一个seq=25368,这个seq并不是随机生成的,而是根据你发的报文这个过程当中慢慢增长上来的,那么接下来,服务端收到了FIN位以后要应答ACK=1,确认消息报文,seq=25369(上一个seq+1),于是客户端就知道服务端已经收到了我的消息,那么真正处理这个过程当中,服务端会接着给客户端发送一个消息,FIN=1,seq=10568,客户端要确认我收到了这个消息,发一个消息确认包回去ACK=1,ack=10569。就这么以来二往,成功断开连接。

思考:第2步和第3步能不能合并在一起?
不可以,因为TCP/IP连接是安全的,是建立在连接上的。首先断开连接是由客户端先发起的,它发起了一个报文,报文里面FIN=1,seq=25368,服务端收到了这个消息,我知道客户端要和我断开连接了。说明了客户端已经完成了,它已经不给服务端发送数据了,客户端已经准备好断开的这个动作了,但是你确保服务端准备好了吗?你确保服务端没有消息要给客户端发了嘛,确认不了。所以逻辑上就要把它拆开。那么客户端要给服务端发送消息以后,服务端只能回复客户端一个ACK=1,它大概的意思就是说:“好的,客户端你断开的申请我收到了,但是我现在还没准备好,你先等一下我的消息,我这边准备好了,我会通知你的。”然后,客户端就在那等,如果服务端所有消息已经全部完成,所有该准备的都准备好,它也能够断开了。这时,服务端给客户端发送一个报文,报文里面FIN=1,还有报文的序列号seq,服务端会告诉客户端:“我要和你分手了”。客户端收到以后,同样回复服务端:“好的,你的消息我收到了,那咱们断开吧。”于是四次挥手结束,整个连接断开。
比较正规一点的描述:
因为客户端要关闭连接的时候,无法保证服务器已经将数据发送完成,所以此时服务器只能告诉客户端我收到你的关闭请求,知道你的数据发送完成。在服务器把数据发送完成之后,告知客户端,数据发送完了,可以关闭连接。此时,客户端也要应答,同意关闭连接

总结

三次握手

三次握手的机制是为了保证能建立一个安全可靠的连接;第一次握手是由客户端发起,客户端会向服务端发送一个报文,报文里面SYN标志位是置1的,当服务端收到这个报文的时候就知道客户端要和我发起一个新的连接,于是服务端就向客户端发送一个确认消息包ACK位置1,以上两次握手之后,对于客户端而言,其实是已经知道了所有信息,就是我既能给服务端发送消息,我还能收到服务端的消息;对于服务端而言,两次握手是不够的,因为到目前为止,服务端只知道一件事情,客户端给我发送的消息我收的到,但是我发给客户端的消息,客户端能不能收到我还不知道。
所以还要进行第三次握手。第三次握手就是当客户端收到服务端发过来的确认消息的报文之后,还要继续给服务端进行一个回应,也是一个ACK位置1的一个确认消息。
通过以上三次连接,不管是服务端还是客户端都彼此知道了,我既能给对方发送消息也能收到对方的消息,那么这个连接就能被安全的建立了。

四次挥手

四次握手机制,也是由客户端首先发起的,客户端会发起一个报文,在报文里面FIN标志位置1;当服务端收到这报文之后,我就知道了客户端想要和我断开连接,但是此时服务端不一定能做好准备,因为当客户端发起断开连接的时候,对于服务端而言它极有可能有未发送完的的消息,它还要继续发送;所以此时对于服务端而言他只能进行一个消息确认,我先告诉服务端,我知道你要和我断开连接了,但是我这还可能没有做好准备,你还需要等我一下,等会我会告诉你;于是,发完这个消息确认包后,可能稍作片刻,它可能会继续发送一个断开连接的报文,一个FIN位置1的报文,是由服务端发给客户端的,这个报文表示了服务端已经做好了断开连接的准备,那么当这个报文发给客户端的时候,客户端同样要给服务端继续发送一个消息确认的报文。一共有四次,通过这四次的相互沟通和连接,我就知道了,不管是服务端还是客户端都已经做好了断开连接的准备,于是连接就可以被断开了。

形象的表示三次握手和四次挥手

三次握手:
男:我们在一起吧,你是我的第40个
女:好的啊,我知道我是你的第40个了,你是我的第8个
男:好的,我是你的第8个,从现在开始吧

四次挥手:
男:我没什么要说的了,你还有的话你继续说
女:我知道了
男方继续听女方balabala
女:我说完了
男:我知道了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵有千堆雪与长街

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值