快速理解TCP三次握手与四次挥手

【TCP是如何建立连接与断开?如何提高可靠性?又是如何提高性能的?】

一、TCP的连接与断开

这里写图片描述
1.连接前的准备
服务端:
分配文件描述符–>绑定–>监听–>阻塞等待客户端连接。
客户端:
分配文件描述符–>发起连接请求–>阻塞等待服务器应答。
2.三次握手
第一次握手:主机A发送同步报文段(SYN)请求建立连接。

第二次握手:主机B听到连接请求,就将该连接放入内核等待队列当中,并向主机A发送针对SYN的确认ACK,同时主机B也发送自己的请求建立连接(SYN)。

第三次握手:主机A针对**主机B**SYN的确认应答ACK。

3.四次挥手
第一次挥手:当主机A发送数据完毕后,发送FIN结束报文段。

第二次挥手:主机B收到FIN报文段后,向主机A发送一个确认序号ACK(为了防止在这段时间内,对方重传FIN报文段)。

第三次挥手:主机B准备关闭连接,向主机A发送一个FIN结束报文段。

第四次挥手:主机A收到FIN结束报文段后,进入TIME_WAIT状态。并向主机B发送一个ACK表示连接彻底释放。

二、面试细节

1.为什么是三次握手?
如果是2次
①当客户端发出一个请求报文段并没有丢失,而是滞留在了某个网络节点,过了好长时间才发送到服务端,此时服务端建立连接。但是由于现在客户端并没有发出连接请求,因此不会理睬服务端的确认,而服务端以为新的连接产生,服务端的好多资源被白白浪费。
②当确认应答ACK总是丢失时,客户端以为服务端没有连接,它将会不断地重新请求连接,而服务端会连接大量的无效连接,给服务器增加维护成本,服务器很容易受到SYN洪水攻击。
如果是3次
就算客户端发送的ACK丢失,也不影响服务端,客户端不断重发,总会连接成功。三次握手相当于将安全问题抛给了客户端,对服务端影响很小。
如果是4次
3次已经很好的解决了,没有必要4次,况且4次也会造成2次握手的问题。

2.为什么是四次挥手?
TCP是面向连接的,属于全双工,断开连接是双方的事情。所以是四次。
当客户端发送FIN结束报文段时,服务端并不会立即关闭SOCKET,所以只能先发送一个ACK。因为有可能此时服务端还没有发送完报文。

3.什么是TIME_WAIT状态?
1)主动断开连接的一方,会进入TIME_WAIT状态,并没有直接进入CLOSED状态。
2)进入TIME_WAIT状态的一方,会等待2倍MSL(最大报文生存时间)的时间。

扫描二维码关注公众号,回复: 1451815 查看本文章

4.为什么客户端在TIME_WAIT状态必须等待2MSL时间?
重发可能丢失的ACK报文。因为客户端在收到服务端真正的关闭连接请求后,会进入TIME_WAIT状态,等待2MSL时间,相当于一个报文一来一回的时间,也就是说,如果客户端的确认应答丢失,算上这个丢失报文的时间,再加上服务端重传FIN的时间(重传后客户端重新启动2MSL计时器),2MSL的时间足够使客户端收到重传的FIN报文段。所以客户端不能立即进入CLOSED状态。
这里写图片描述

三、TCP可靠性机制。

1.检验和
典型的有CRC校验法。在要传输的k比特数据D后添加(n-k)比特冗余位。
2.序列号
通过序列号,可以去重、超时重传、数据有序到达。
3.确认应答
可以确认ACK之前的数据肯定到达了,保证了可靠性。
4.超时重传
发送的数据有可能因为网络拥堵,没有及时到达,发送端没有收到确认,就会进行重发。
接收端有可能收到许多重复文件,通过序列号可以去重。
累计到一定次数,TCP认为网络或者接收端出现异常,强制关闭连接。
5.连接管理
通过三次握手四次挥手,也可提高可靠性。
6.流量控制
接收端处理数据的速度是有限的,如果发送端发的太快,接收端缓冲区容易满,会造成丢包以及引起丢包重传。

1.接收端将自己可以接收的缓冲区大小放入报头窗口大小中,通知发送端。
2.窗口大小越大,说明网络的吞吐量越高。
3.接收端如果发现自己的缓冲区快满了,就会将自己的窗口大小调低,发送端收到后会降低自己
的发送速度。
4.如果接收端满了,将自己的窗口大小设置为零,发送不在发送数据,但是会定期发送一个窗口
大小探测数据段。

7.拥塞控制
发送数据的时候,不能刚开始就发送大量的数据,所以在不清楚网络状况的情况下,不能贸然发送大量的数据,有可能加重网络负担,TCP会使用慢启动机制,探探路,所以刚开始的时候,将拥塞窗口设为1,以后是指数增长,当达到阈值的时候,按照线性增长,到达拥塞窗口的最大值后,拥塞窗口重回1。

拥塞窗口:网络的接收能力。
慢启动机制:初始时慢,但是增长速度非常快。
慢启动阈值:当拥塞窗口超过这个阈值的时候,按照线性方式增长。
          当TCP开始启动的时候,慢启动的阈值等于窗口最大值。
          在每次超时重传时,慢启动阈值变为原来窗口最大值得一半,同时拥塞窗口设置为1。

少量的丢包:触发超时重传。
大量的丢包:我们认为是网络拥堵。
TCP通信开始后,网络吞吐量会逐渐上升,当网络拥堵,情况相反。

四、提高性能

1.滑动窗口
当每发一个段就进行一次确认,这种方式性能太差。所以我们可以一次多发送几个,然后进行确认。当收到一个ACK后,滑动窗口向后移动,继续发送第五个段的数据。操作系统为了维护这个滑动窗口,需要开辟缓冲区(记录当前哪些数据没有应答),发送了的数据才能从缓冲区中删除。
这里写图片描述

窗口大小:指无需等待确认应答而可以继续发送数据的最大值。窗口越大,网络的吞吐量越高。
2.快速重传
高速重发控制也叫做快重传。当某一报文段丢失后,发送端会一直收到丢失段的确认应答,在窗口较大时,会出现报文段丢失的情况,同一个序号的确认应答将会被重复不断的返回,如果发送端主机连续三次收到同一个确认应答(因为三次才会触发重发机制)就会将对应的数据进行重发。
这里写图片描述
3.延迟应答
假如接收端的缓冲区的大小为1M,一次收到的数据为500K,如果立刻应答,那么返回窗口就是500K,倘若接收端接收能力特别强,500K的数据早就接收完毕,那么当接收端稍微迟一点应答,它马上处理完500K的数据,那么它就可以返回窗口的大小为1M,提高了网络的吞吐量。
但是延迟应答也有数量限制和时间限制,不可能一直不应答。
4.捎带应答
可以提高效率,客户端与服务端在一发一收(互发数据),ACK可以搭顺风车。TCP的确认应答和回执数据可以通过一个包发送。

五、其他概念

1.面向字节流
专业指:不包含边界数据的连续流。
UDP的读和写需要一一匹配,对数据包不拆分,是多大,就一次发送多大。
TCP的读和写不需要一一匹配,可以一次发送几个字节(随意),这种叫做面向字节流。
2.粘包问题
虽然在传输层,这些报文是一个一个发送的,按照序号排放在缓冲区中,但对应用程序来说,是一连串连续的字节数据,像包子一样粘住了。所以我们应该明确两个包之间的边界。
1)对于定长的包,每次按固定大小来读。
2)对于变长的包,在包头位置约定一个包总长度的大小。
3)利用分隔符(保证分隔符与正文数据不起冲突)。
注:UDP不存在粘包问题。因为UDP每次发送一个完整的数据包。

猜你喜欢

转载自blog.csdn.net/guorong520/article/details/80347168