tcp/ip|三次握手和四次挥手知识总结(超详细)

前言:
最近学习了计算机网络的知识,看了很多的视频,并参考了很多资料,写下了这将近4500字的与“三次握手和四次挥手”相关的知识,希望能帮助到各位小伙伴儿以及加深自己印象,方便以后复习用
如果有什么写的并不准确的地方,还请大佬不吝赐教
tcp/ip|三次握手和四次挥手知识总结(超详细)
文章图片

【tcp/ip|三次握手和四次挥手知识总结(超详细)】
文章目录

  • TCP报文段的首部格式介绍
  • 三次握手
  • 两次握手为什么行不通
  • 半连接队列和全连接队列
  • 四次挥手
  • 为什么四次挥手,三次挥手不行吗

TCP报文段的首部格式介绍 tcp/ip|三次握手和四次挥手知识总结(超详细)
文章图片

tcp/ip|三次握手和四次挥手知识总结(超详细)
文章图片

源端口:占 16位2个字节发起通信的那个进程
目的端口:占 16位2个字节接收通信的那个进程
序号(seq):占 32位4 个字节,序号范围[0,2^32-1],序号增加到 2^32-1 后,下个序号又回到 0。TCP 是面向字节流的,通过 TCP 传送的字节流中的每个字节都按顺序编号,而报头中的序号字段值则指的是本报文段数据的第一个字节的序号。例如:我们的seq = 201,携带的数据有100,那么最后?个字节的序号就为300,那么下?个报?段就应该从301开始.
确认号(ack):占 32位4 个字节,期望收到对方下个报文段的第一个数据字节的序号。当标志位ACK值为1时,才能产生有效的确认号ack。并且:ack=seq+1;
RST:当RST=1时,表明TCP连接出现严重错误,此时必须释放连接,之后重新连接,?叫重置位.
URG:紧急指针标志位,当URG=1时,表明紧急指针字段有效.它告诉系统中有紧急数据,应当尽快传送,这时不会按照原来的排队序列来传送.?会将紧急数据插?到本报?段数据的最前?
ACK:当ACK=1时,我们的确认序列号ack才有效,当ACK=0时,确认序号ack?效,TCP规定:所有建?连接的ACK必须全部置为1
PSH:推送操作,提示接收端应用程序立即从TCP缓冲区把数据读走
SYN:同步序列号标志位,tcp三次握?中,第?次会将SYN=1,ACK=0,此时表?这是?个连接请求报?段,对?会将SYN=1,ACK=1,表?同意连接,连接完成之后将SYN=0
FIN:在tcp四次挥?时第?次将FIN=1,表?此报?段的发送?数据已经发送完毕,这是?个释放链接的标志
PS:ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号
16位窗?的??:win的值是作为接收?让发送?设置其发送窗???的依据.
紧急指针:只有当URG=1时的时候,紧急指针才有效,它指出紧急数据的字节数.
三次握手 tcp/ip|三次握手和四次挥手知识总结(超详细)
文章图片

三次握手,顾名思义就是客户端与服务端进行三次通信。
tcp/ip|三次握手和四次挥手知识总结(超详细)
文章图片

刚开始客户端处于关闭(Closed)状态,服务器处于监听(Listen)状态。
第一次握手 : 客户端给服务器发送SYN报文,初始的序列号为x,并且需要消耗一个序号。此时客户端进入SYN_SENT状态。
当SYN=而ACK=时,表明这是一个连接请求报文。
注意SYN=1时的报文段是不能携带数据的,因此第一次握手和第二次握手客户端和服务端都不能携带数据。 这是因为如果可以携带数据的话,假如有人想要攻击服务器,只需要每次在第一次握手时在SYN报文放入很多数据,重复发送这些大量的SYN报文,服务器就会花大量内存缓冲这些报文,服务器就更加容易被攻击了。
第一次握手服务端可以看出 :客户端的发送能力,和自己的接收能力处于正常状态
第二次握手:服务端收到来自客户端的SYN报文后,对这个SYN报文确认后,会把自己的SYN报文响应给客户端,此时ACK=1表示确认序列号有效,SYN=1也不能携带数据,并且确认号(ack)的值为传来的seq+1,即为x+1,此时初始序号为y。此时服务器进入SYN_RECV状态
第二次握手客户端可以看出:服务端的发送和接收能力都正常,客户端的发送和接收能力也都正常,但重要的一点是服务端不知道客户端的接收能力是否正常。
第三次握手:客户端收到了服务器SYN+ACK的包,此时客户端处于ESTABLISHED状态并且客户端和服务端均表示同意连接,因此会发送一个ACK报文,确认号ack的值仍为序列号+1,即y+1,初始seq值为x,所以第二个报文段seq+1,即x+1。
第三次握手可携带数据,不携带数据则不消耗数据
第三次握手可以看出: 客户端的发送接收,服务端的发送接收能力均正常。
两次握手为什么行不通 首先举一个生活中常见的例子:
此时你和你的对象拨通了电话(没对象就自己new一个):
你 :“喂,能听到我说话吗?”
你对象 :“亲爱的,我可以听到!”
此时你突然不说话了…
tcp/ip|三次握手和四次挥手知识总结(超详细)
文章图片

试想一下,你(new 的)对象现在肯定怀疑是不是自己的麦克风有问题或者自己的网有问题,导致你听不见…
tcp/ip|三次握手和四次挥手知识总结(超详细)
文章图片

因此在这里也是如此,仅两次握手,服务端不知道客户端是否能接收到自己给它的通信,所有三次握手是可行的。
另外,三次握手是安全的,并且节约资源
如果客户端发送请求时出现了丢包情况,因为自己没发送,又重新传了一遍,然而等数据传输完成后客户端和服务端都释放了连接,第二次传输的数据在释放连接前给服务器传了过去,但第一次传输的数据假如由于网络原因滞留的时间长了,在释放连接后到达了服务端,这个时候服务端就会误以为客户端又发出了一次新的请求,服务端确认了客户端第一次发出的报文段并同意建立了新的连接,发送报文给客户端,此时服务端会一直等待客户端的答复,而客户端此时正处于释放连接状态,所以导致白白浪费了资源。
半连接队列和全连接队列 半连接队列(syn queue)
客户端发送SYN包,服务端收到后回复SYN+ACK后,服务端进入SYN_RCVD状态,此时双方还没有完全建立连接,这个时候的socket会放到半连接队列。
全连接队列(accept queue)
当服务端收到客户端的ACK后,socket会从半连接队列移出到全连接队列。当调用accpet函数的时候,会从全连接队列的头部返回可用socket给用户进程。全连接队列中存放的是已完成TCP三次握手的过程,等待被处理的连接,在客户端及服务端的状态均为 ESTABLISHED
tcp/ip|三次握手和四次挥手知识总结(超详细)
文章图片

四次挥手 四次挥手,顾名思义就是客户端和服务端四个步骤的释放连接,断开连接需要发送四个包,别名连接终止协议。由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
tcp/ip|三次握手和四次挥手知识总结(超详细)
文章图片

刚开始客户端和服务端都处于ESTABLISHED状态,假如客户端主动发起关闭请求:
第一次挥手:TCP客户端向服务端发送一个FIN报文,用来关闭客户端到服务端的数据传送,其中包含一个序列号seq=u,发送完后,客户端进入**FIN_WAIT_1状态,**即主动关闭TCP连接,不再发送数据,(但是可以接收服务器发来的报文),等待服务端回复。
第二次挥手:服务端接收到FIN报文后,会发回一个ACK,表明自己已经接收到了此报文,(此时客户端接就知道服务端接收到了自己的断开连接请求),(但是服务端可能还有数据要传输),并且seq=v,ack的值为序列号+1,此时服务端进入CLOSE_WAIT关闭等待状态。和SYN一样,一个FIN将占用一个序号。这个时候TCP处于半关闭状态,当客户端接收到服务端的回复后,进入FIN_WAIT_2终止等待2状态。
第三次挥手:服务器关闭客户端的连接,发送一个FIN报文给客户端,并且指定一个序列号,ack的值为u+1,此时服务器处于LAST_ACK最后确认状态,等待客户端回应。
第四次挥手 :客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答(ack = w+1),且把服务端的序列值 +1 作为自己 ACK 报文的序号值(seq=u+1,此时客户端处于 TIME_WAIT(时间等待状态)。TIME-WAIT状态是为了等待足够的时间以确保远程TCP接收到连接中断请求的确认。
注意 :
这个时候由服务端到客户端的 TCP 连接并未释放掉,客户端需要经过时间等待计时器设置的时间 2MSL(一个报文的来回时间) 后才会进入CLOSED状态(这样做的目的是确保服务端收到自己的 ACK 报文。如果服务端在规定时间内没有收到客户端发来的 ACK 报文的话,服务端会重新发送 FIN 报文给客户端,客户端再次收到 FIN 报文之后,就知道之前的 ACK 报文丢失了,然后再次发送 ACK报文给服务端)。服务端收到 ACK 报文之后,就关闭连接了,处于 CLOSED 状态。
这里解释一下需要等待2MSL的原因:
1、防?客户端最后?次发给服务器的确认在?络中丢失以?于客户端关闭,?服务端并未关闭,导致资源的浪费。
2、等待最?的2msl可以让本次连接的所有的?络包在链路上消失,以防造成不必要的?扰。
如果客户端t直接closed,然后?向服务端r发起了?个新连接,我们不能保证这个新连接和刚关闭的连接的端?号是不同的。假设新连接和已经关闭的?端?号是?样的,如果前?次滞留的某些数据仍然在?络中,这些延迟数据会在新连接建?后到达服务端,所以socket就认为那个延迟的数据是属于新连接的,数据包就会发?混淆。所以客户端要在TIME_WAIT状态等待2倍的MSL,这样保证本次连接的所有数据都从?络中消失
为什么客户端需要TIME_WAIT状态:
假设最终的ACK丢失,服务端将重发FIN,客户端必须维护TCP状态信息以便可以重发最终的ACK,否则会发送RST(TCP连接出现错误),结果服务端认为发生错误。TCP实现必须可靠地终止连接的两个方向(全双工关闭),客户端必须进入TIME_WAIT 状态,因为客户端可能面临重发最终ACK的情形。
tcp/ip|三次握手和四次挥手知识总结(超详细)
文章图片

为什么四次挥手,三次挥手不行吗 首先为什么握手是三次,而挥手是四次:
因为握手的时候并没有数据传输,所以服务端的 SYN 和 ACK 报文可以一起发送,但是挥手的时候有数据在传输,所以 ACK 和 FIN
报文不能同时发送,需要分两步,所以会比握手多一步。
其次为什么三次挥手不可行:
因为服务端在接收到FIN, 往往不会立即返回FIN ,必须等到服务端所有的报文都发送完毕了,才能发FIN。因此先发一个ACK表示已经收到客户端的FIN,延迟一段时间才发FIN。这就造成了四次挥手。
如果是三次挥手会造成:
如果将服务端的两次挥手合为一次,等于说服务端将ACK和FIN的发送合并为一次挥手,这个时候长时间的延迟可能会导致客户端误以为FIN没有到达客户端,从而让客户端不断的重发FIN。所有只能第二次握手先发送ACK确认接收到了客户端的数据,等服务器发送完了数据,再发送FIN包进行第三次挥手。
用一个生活中的案例来说明
前提:假如你在外边玩,此时你拨通了妈妈的电话
1.你:“娘亲俺饿了,能给我做一份香喷喷的合罗面吗”
2.你的妈妈:“好,我现在准备准备,买买菜,等会做好了喊你”
。。。。。。家长做饭的过程。。。。。。
3.你的妈妈:“儿砸,饭做好了,该下面条了,什么时候回来呀”
4.你:“好嘞妈,你先下面条吧,我正在上楼”
( 。。。。最后,你吃上了香喷喷的合罗面,并表示:妈妈的味道。。。。)
通过此例子,第二个步骤和第三个步骤肯定不能合并,因为第二个步骤妈妈确定了,你饿了,但还没有做好饭,所有等饭做好了(数据发完了),才会通知你一切都准备好了。
文章到这里就结束了,这方面的知识面试的时候问的还是挺多的,希望各位各位小伙伴以及我都能把这些知识学透学扎实,面试的时候都不怕。如果您看完了此文章,觉得有什么不准确或者需要改进的地方,请大佬指正。或者有什么不懂的地方,都可以提出来,会耐心解答的。
再次感谢各位小伙伴儿
tcp/ip|三次握手和四次挥手知识总结(超详细)
文章图片

    推荐阅读