【Linux】 --你知道TCP三大特性的具体含义吗?

众所周知TCP协议的特点:面向连接,可靠传输,面向字节流,接下来,我们便一一对这些特性做一个详细的讲解

一、TCP三大特性之面向连接

面向连接重点:三次握手建立连接,四次挥手断开连接

- 三次握手建立连接

如下图所示,客户端和服务端在建立连接前都要进行三个步骤(图中红色文字的介绍,三次握手在后面):
在这里插入图片描述
对上图中的标数字的步骤进行详细讲解
1)客户端发送链接请求,并且封装报头,将报头中的SYN置为1,服务端收到请求,并且新建了一个套接字,即new socket,进入一个新的状态叫做SYN-RCVD
2)服务端收到请求,给出一个确认回复SYN+ACK ,客户端收到这个信息后,进入EATABLISHED状态,认为服务端具有数据收发能力,他也给服务端回复一个确认ACK
3)客户端收到服务端的信息后,给服务端回复一个确认ACK,服务端收到ACK后也进入一个ESTABLISHED状态,认为客户端也具有数据收发能力,那接下来双方就可以收发数据了。

- 为什么需要三次握手,而不是两次?

大家应该都纠结过这个问题,往下看吧,因为TCP是一个双工通信,需要都确定对方具有数据收发能力,都得给对方发送数据连接请求,等待对方回复,那这里你也许会问,客户端发送一个连接请求,服务端收到后进行回复确认并发送一个连接请求,不就只有两次吗,要三次不多余吗?醒醒吧,那你有没有想过万一服务端给客户端的确认信息丢失了怎么办?客户端还在傻傻等着回复信息,他也不知道自己的请求人家收到了没,也不知道起始序号,也不知道数据如何发送,只能等着。所以,两次真的不够,三次才是最合适的。

- 四次挥手断开连接

当数据发送完完毕,自然是要断开连接,如下图所示:
在这里插入图片描述
对以上标数字的过程的解释:
1)客户端调用close接口,给对方发送一个FIN包,自己进入FIN_WAIT1状态,表示自己不再向服务端发送数据了
2)服务端收到请求后,给客户端发送一个确认ACK,表示自己收到客户端不再发送数据的请求。服务端进入一个状态叫做CLOSE_WAIT状态,客户端进入FIN_WAIT2状态。
3)服务端给客户端发送一个连接断开的请求,即就是FIN包,调用close接口,进入LAST_ACK 状态
4)客户端收到FIN包,发送完确认ACK后,进入TIME_WAIT状态,服务端收到ACK后进入CLOSED,立即销毁资源

  • 为什么挥手是四次?

有可能被动关闭方还有数据要发送,像是客户端发送连接断开请求并发送FIN包,但是并不表示他不接收数据,而服务端对发来的FIN包进行回复,但可能他还有数据要发送,只有等用户确认数据发送完毕了,关闭了套接字,服务端才能发送FIN包来断开连接。即就是ACK和FIN包是分别进行发送的,而不是跟三次握手一样放在一起发送的,因此挥手必须是四次,懂了吗?

  • TIME_WAIT的作用是什么?

假设一下并没有TIME_WAIT,那主动关闭方套接字会直接被释放,直接进入CLOSED状态,如下图所示,如果最后一次的ACK丢失,那服务端会重新发送FIN包,那就会对客户端的新连接造成影响(比如其他服务器会给他发送SYN连接请求),因此会等待两个MSL的时间,也就是重传的FIN包和回复ACK的时间
在这里插入图片描述

  • 连接管理中的保活机制是指什么?

看到这里,我们可能会有疑问为什么需要保活?不要可不可以?小伙子,你忘了吗?TCP可是面向连接的,只有通信双方相互建立了连接,才能够通信,若很长时间双方都没有通信,我们也很难保证双方是否在线,因此TCP就会默认一个保活机制,来探测连接是否健全。

所以保活机制就是

  • 若通信双方长时间(7200s)无数据往来,则服务端每隔一段(75s)时间就会向客户端发送一个保活探测数据包,要求对方回复。
  • 若多次(9次)都没有得到相应,则认为连接断开
  • 反应就是recv返回0,send触发一个SIGPIPE异常

二、TCP三大特性之可靠传输

(1)确认应答机制:我发送一条数据给你,你必须给我一个回复,说明数据已经到达了,如果很长时间没有给与回复,便要用到我们的第二条特性(超时重传)
(2)超时重传机制:长时间没有收到确认信息,超过指定的时间,便重新发送数据
(3)协议字段的序号/确认序号:由于我们发送的数据都是有序号的,对方收到数据后,它在缓冲区里面会对数据按照序号进行排序,进行包序管理。另外序号还有一个作用,如下图所示:
在这里插入图片描述
客户端发送数据1、2、3,服务端给出确认ACK信息,但是不巧的是,1号数据是收到了,但是返回的确认ACK的信息丢了,2,3号的ACK到达,那么序号的作作用就来了,我们已经收到2号信号的确认信息,那就默认之前的数据全都接收到了,不用再重新发送。
(4)协议字段中的校验和:当某一端收到数据后,通过二进制反码求校验和,看收到的数据是否一致,不一致则重传。(求校验和之前在计算机网络书上看到一种方法叫做CRQ循环冗余校验法,感兴趣的可以了解下,小声嘀咕)
(5)面向连接:确保双方都具有数据发送的能力

但是这里也存在一些问题:

  • TCP可靠传输中如何避免丢包?

都知道丢包之后会重传数据,那自然效率也就降低了,那我们是如何避免丢包的?答案是滑动窗口机制。
滑动窗口协议如何实现:通过一个窗口后沿(保存序号的变量)和一个窗口的前沿,以及当前的一个发送序号

窗口从发送区的缓冲区的起始位置开始,每次发送一个数据太慢,滑动窗口给这些数据规定一个范围,每次发送这个范围内的数据,当我受到前面数据的确认响应,则窗口向后移动
在这里插入图片描述

而接收方也会维护一个窗口,因为数据有序号,当我收到前面的数据,那窗口就会向后移动,而接收到后面的数据是不移动的
在这里插入图片描述

  • 在TCP三次握手阶段,通信双方会协商一个最大数据段大小–MSS,用户send发送数据会将数据发送到缓冲区中,然后操作系统会从缓冲区中取出小于MSS大小的数据,封装tcp头部发送出去。
  • tcp在每次发送数据的时候,都会给对方在报文头部中发送一个字段,告诉对方最多一次能给自己连续发送多少数据,(这个窗口大小不能大于接收缓冲区的剩余空间大小)

其实前面讲的是后面的铺垫,那到这里我们还是不知道他为什么能够防止丢包呀???继续看下面,有三点原因:

  • 发送方可以连续发送多条数据,等待对方回复,提高性能
  • 连续发送数据,连续确认回复,可以避免因为确认回复信息的丢失而导致数据重传
  • 流量控制,接收方根据自己接收缓冲区的剩余空间大小,向发送方返回窗口大小,逆置发送方发送速度,避免对方因为发送数据过多导致满溢,使得数据丢包

快速重传机制

还记得本文之前讲过的协议字段的序号和确认序号吗??不记得可以看看,之前说我们收到一号数据,但是确认回复信息丢失了,只要我们收到后面数据的ACK就可以确认1号已经收到了。那万一就没有收到1号信号呢,怎么办?对,这就是快速重传。
当接收方接收到第二条数据,未收到第一条数据,则认为数据有可能丢失,这时候连续发送三次数据重传请求,当发送方连续收到三条重传请求后,将数据重传

三、TCP三大特性之面向字节流

先记住这几个字眼:
面向字节流:有序,可靠,双向,基于连接的字节流传输
面向字节流服务比较可靠,但是会出现黏包问题。

  • 什么是TCP的黏包?
    TCP在传输层对数据边界并不敏感,(并不管什么类型的数据或者多少数据,只管发送合适大小的数据)导致多条数据合成一条数据进行处理,黏包在接收方和发送方都有可能发生
  • 如何解决黏包?
    需要用户在应用层进行一个数据边界的管理
    (1)数据定长:规定数据的长度
    (2)特殊字符进行间隔
    (3)在不定长数据的应用层头部中添加数据长度字段:接收欧方根据头部长度,接收该长度的数据

以上就是关于TCP三大特性的所有内容,有问题的话希望广大读者给与建议,一定虚心采纳

发布了33 篇原创文章 · 获赞 13 · 访问量 1050

猜你喜欢

转载自blog.csdn.net/Vicky_Cr/article/details/104535104