目录
前言
一. 可靠数据传输
1. 确认应答机制
2. 超时重传机制
二. 建立连接(三次握手)
1.建立连接的过程
2. 为什么会有三次握手?
3. 三次握手可以携带数据吗?
4. 什么是半连接队列?
三. 断开连接(4次挥手)
1.4次挥手的过程
2.为什么连接是3次握手,断开时是4次挥手呢?
3.TIME_WAIT有什么作用,为什么主动关闭一方不直接进入CLOSED状态?
4. 为什么TIME_WAIT的时间是2MSL?
5. 如果一台服务器上存在大量的CLOSE_WAIT是什么原因,应当怎样处理?
6.解决TIME_WAIT状态引起的bind失败的方法
7. 查看TCP的连接状态
- 个人主页:努力学习的少年
- 版权: 本文由【努力学习的少年】原创、在CSDN首发、需要转载请联系博主
- 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦
上一篇文章讲了TCP报文段的结构,如果不熟悉TCP报文段的话,那么这篇文章很可能看不懂哦,点开下方连接去了解TCP报文段的结构吧:
【网络自定向下学习】——TCP报文段的详细解析
在因特网络层服务(IP服务)是不可靠的。IP不保证数据报的交付,不保证数据报的按序交付,对于IP服务,数据报有可能因在路由器缓存中溢出而永远不能到达目的地,数据报也有可能是乱序到达,而且数据报中的比特可能受损(由0变为1或者相反)。因为运输层报文段是被IP数据报携带者在网络中运输的,所以运输层的报文段也会遇到这种问题。
TCP是IP的不可靠的尽力而为服务的基础上建立了一种可靠数据传输服务,为了保证数据能够达到目的地,TCP采用了确认应答机制和超时重传机制。
发送方是怎样保证接收方收到自己发送的报文段呢?当接收方收到发送方的报文段的时候,会给发送方发送一个ACK设置为1的报文段,且在确认序号中填充seq+1的数值,表示seq及之前的所有数据都已经接收到了,当发送方收到响应报文段后,就知道接收方已经收到自己发送的报文段。(ps:seq是序列号)
确认应答机制能够使发送方验证发送的数据已经达到接收方,但是发送出去的数据有可能出现丢包的现象或者接收方发送的ACK报文段丢失了。这样发送方就收不到应答报文报文?那么TCP怎样检测丢包以及发生丢包后该做些什么?
TCP采用的是超时重传机制来解决这个问题,
举个例子:
假定主机A发送一个TCP报文段給主机B,主机A便会启动一个倒数定时器记录该报文段的发出去时间。该报文段可能在网络途径中发生了丢失(如图一),或者主机B收到报文后发送給主机A的ACK报文丢失(图二),在这两种情况下,主机A都收不到主机B的ACK响应。那么当倒数定时器时间到了的时候,主机A就需要重传该报文段,然后在重新启动一个定时器记录时间,直到收到该报文段的响应,主机A才会丢弃该报文段。
当客户机处于ESTABLISHED状态时,TCP客户机就能发送报文段和接收包含有效载荷(即应用层产生的数据)的TCP报文段。
客户机建立好连接和服务器建立好连接是有时间差的,在连接的过程中,第一个报文段和第二个报文段是不用担心丢失的问题,因为这两个报文段有确认应答和超时重传机制,可以确保前两个报文段对方收到,但是,当客户机发送第三个报文段的时候,是不能保证服务器能够接收到该报文段的,因为第三个报文段没有应答的报文,所以当第三个报文段丢失时,此时就只有客户机建立好了连接(创建接收缓冲区和发送缓冲区资源),由于服务器在一段时间内没有收到ACK,那么服务器此时就超时了,就会給客户机发送一个RST报文段給客户端,断开连接,进入CLOSED状态,让客户端重新发起连接请求。
原因一:
三次握手是验证双方都能够相互通信最少次数,tcp通信需要确保双方都具有数据收发的能力,得到ACK响应则认为对方具有数据收发的能力,因此双方都要发送SYN确保对方具有通信的能力。
第一次握手,客户端发送SYN,服务端接收,服务端接收后得出客户端的接收能力和服务端的接收能力都正常。第二次握手,服务端給客户端发送SYN+ACK得出客户端的接收能力和发送能力正常,服务器的接收能力和发送能力正常。如果是只有两次握手的话,服务端不知道自己发送能力和客户端能力是否正常,因此第三次握手客户端給服务器发送ACK,服务端接收后才能得出服务端的发送能力正常和客户端能力正常。
原因二:
服务器: 客户端的关系一般都是1:n,也就是说1台服务器是可能有多个客户端连接,因此服务器上的资源是十分宝贵的,如果是两次握手的话,服务器接收到第一个SYN报文就建立好连接,分配好资源,那么有可能造成服务器上的资源浪费掉了。因为服务器不知道自己发送能力和客户端的接收能力是否正常,如果它们都异常,那么服务器上建立连接,分配好的资源就浪费掉了。如果一台服务器同时接收到10000个连接,有2500个连接失败的话,那么服务器浪费的资源是相当大的.通过三次握手,服务器至少可以确保双方连接成功,避免资源浪费。
答:第一次和第二次握手是不能携带数据的,第三次握手是可以携带数据的。
答:服务器会收到第一次SYN,就会处于SYN_RECV状态,由于双方还没有完全建立好连接,服务器会把这些连接放在一个队列中,这个队列就叫做半连接队列。还有一个是全连接队列,也就是已经完成三次握手的连接放在一个队列中,该队列就叫做全连接队列,如果队列满了,那么就有可能出现连接失败的问题。
TCP在握手的过程中,其中服务端可以将SYN和ACK合并一个报文段发送給客户端。所以减少了一次报文段的发送。当客户端关闭连接的时候,給服务端发送FIN报文段时仅仅告诉服务端:自己将不再发送数据,但是服务端那边可能还有一些数据还没有发送或者还有一些数据没有处理,不能立刻关闭服务端和客户端的通信信道,服务端只能先回应一个ACK报文表示你的FIN报文我已经收到了,等到服务端处理完数据后,服务端才会发送一个FIN报文段給客户端,因此服务端的ACK和FIN报文段不能合并发送給客户端,所以4次挥手就需要4次数据包的交互。
TIME-WAIT 作⽤是等待⾜够的时间以确保最后的 ACK 能让被动关闭⽅接收,从⽽帮助其正常关闭。如果主动方收到FIN后直接进入CLOSED状态时,那么当最后一个ACK丢失的时候,被动关闭的一方超时会发送一个FIN給主动的一方,此时主动方收到FIN报文那么,就不会給被动的一方发送ACK报文,那么被动关闭的一方将保持FIN_ACK状态,资源也不会被释放掉。
MSL是报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文就会被丢弃
.在客户端給服务端发送一个ACK包,这个可能在达到不了,在一定时间内,如果服务器收不到ACK包,那么服务器就会重新給客户端发送一个FIN包,所以客户端发送ACK报文段后就需要留出2MSL时间(ACK到达服务器的时间+服务器的FIN到达客户端的时间,一来一回),如果在2MSL时间内没有收到FIN包,那么客户端就认为服务端已经关闭连接。
在 Linux 系统⾥ 2MSL 默认是 60 秒,那么⼀个 MSL 也就是 30 秒。Linux 系统停留在 TIME_WAIT 的时间为固定的 60 秒。
如果一台服务器上存在大量的CLOSE_WAIT很可能是编码的时候没有调用close()函数释放连接资源,所以我们加上一个close将连接资源給释放掉即可。
如果服务器因为某种原因导致服务器崩溃了,那么服务器就会主动断开TCP连接,我们前面讲过,主动断开连接的一方就会进入TIME_WAIT状态,那么此时我们要想快速重新启动服务器,并绑定原来端口号时,那么就可能会出现bind error的现象,如果要想快速重新启动该服务器并绑定原来的端口号,那么我们需要在创建套接字后,就将socket描述符的选项SO_REUSEADDR设置为1.表示允许套接口和一个已在使用中的地址捆绑。所以我们创建tcp服务器的时候,必须进行如下操作。
到此为止TCP三次握手和4次挥手就讲解完了,同时也欢迎大家在评论区上同博主进行交流,如果有什么问题,我也可以给大家提供支持。
最后,如果觉得文章对你有帮助的话,请给博主关注,点赞,收藏,博主将会不断做出优质的文章给大家。
系列文章
3.【网络自定向下学习】——TCP报文段的详细解析
4. 【网络自定向下学习】——TCP报文段的详细解析