TCP的一些概念
TCP: Transmission Control Protocol, 传输控制协议
零、TCP是什么
TCP的特点是相对于UDP而言的.既然是feature,就有和其他协议有不同的地方才能称之为 feature.
- 特点: 面向连接(首发数据前,必须建立可靠的连接)
- 建立连接基础: 三次握手
- 应用场景: 数据必须准确无误的收发 HTTP请求、FTP文件传输、邮件收发
- 优点: 稳定、重传机制、拥赛控制机制、断开连接
- 缺点: 速度慢、效率低、占用资源、容易被攻击(三次握手 -> DOS、DDOS攻击)
TCP/IP协议组: 提供点对点的连接机制,制定了数据封装、定址、传输、路由、数据接受的标准.
我们绝大多数的连接都是使用TCP协议进行传输控制.
一、TCP三次握手
建立TCP连接的前奏
标识位 | 数据包 |
---|---|
SYN | Synchronize Sequrnce Numbers 同步序列编号 |
ACK | Acknowledgement 确认字符 |
状态
名称 | 作用 |
---|---|
LISTEN | 监听TCP杜阿口的连接请求(我等着你发送连接请求呢) |
SYN-SENT | 在发送连接请求后等待匹配的连接请求(我发送了连接请求,我等你回复哈) |
SYN-RECEIVED | 在收到和发送一个连接请求后等待对连接请求的(我收到你的连接请求了哈, 我等你回复我) |
ESTABLSHED | 代表一个打开的连接,数据可以传送给用户(建立了连接,我和你说一下) |
TCP连接图示
![[截屏2022-01-27 15.22.25.png]]
- 第一次握手: 客户端向服务端发送SYN标志位(序号是J), 并进入SYN_SENT状态(等待服务端确认状态)
- 第二次握手: 服务端收到来自客户端的SYN J, 服务端会确认该数据包已收到并发送ACK标志位(序号是J + 1)和SYN标志位(序号是K), 随后进入SYN_REVD状态(请求接受并等待客户端确认状态)
- 第三次握手: 客户端进入连接建立状态后,向服务端发送ACK标志位(K+ 1) , 去人客户端已收到建立连接去人,服务器收到ACK标志后,服务端进入连接已建立状态.
J 和 K 都是为了确立是谁在请求. SYN和ACK的结构没有什么不同,只是发送的对象不一样. 图中线条下面的可以很好的解释SYN J 是什么意思.就是 发送序号 200, 序号是SYN . J 可以是200
序号的定义
假如一个TCP连接的第一个报文序列号(ISN)是0,那么后续每个报文的序列号是固定的。
但是为了防止黑客使用TCP Spoof方法攻击,这个ISN要求是随机的,避免被黑客猜到。在Windows的不同版本,或者Linux的不同版本,这个随机的方法都不太一样。 RFC1948里建议的随机算法是
ISN=M+F(localhost, localport,remotehost, remoteport)
其中M是一个计时器,每4毫秒加1。F是一个Hash算法,比如MD5或者SHA256。 TCP协议要使用的序列号是后面报文实际携带的序列号和ISN的相对值。
为什么不是两次、四次呢:
这个是知乎的答案: www.zhihu.com/question/24…
有一些信息是能够明白的:
- 本来TCP握手应该是四次的,但是吧第三次和第四次给合并起来了设计了.变成了现在的三次握手.
- SYN和ACK以及三次握手的设计都是为了保证客户端和服务端之间的时钟能够对得上.
- 三次握手是保证了基本的可靠率,四次、五次、六次当然是更加可靠的,但是这个可靠率并没有提升多少.所以在性能和可靠率之间去一个平衡的话,三次是最合适的.
二、TCP四次挥手
![[截屏2022-01-27 15.25.06.png]]
在TCP连接之后,就可以进行HTTP的连接传输数据了. 如果数据传输完毕之后 ,肯定是要关闭TCP连接的.而关闭TCP连接就需要经过4次挥手.
关闭TCP连接的前奏
- FIN: finsh 关闭连接
状态:
- FIN-WAIT_1: 等待远程TCP的连接中断请求,或先前的连接中断请求的确认
- FIN-WAIT-2: 从远程TCP等待连接中断请求
- CLOSE-WAIT: 等待从本地用户发来的连接中断请求
- LAST-ACK: 等待原来发向远程TCP的连接中断请求的确认
- TIME-WAIT: 等待足够的时间以确保远程TCP接收到连接中断请求的确认
- CLOSED: 没有任何连接状态
- **TIME-WAIT时长:**2MSL Maximum Segment Lifetime 最大报文生存时间
- MSL的值根据不同的情况而不同,一般是30秒 1分钟 2分钟
- 目的:保证客户端发送的最后一个报文能够发到服务器,一旦报文丢失,服务器会认为,自己最后一次发送的FIN+ACK包,客户端并没有收到,此时,服务器会重新发送一次FIN+ACK包,而客户端可以 在2MSL的TIME-WAIT时间内收到重新传输的FIN+ACK包,接着重新进行第四次挥手,并重启2MSL计时器。
CLOSE-WAIT和 FIN-WAIT 是一回事.只是前者是服务端等待中断请求,后者是客户端等待中断请求的状态
TCP关闭连接的过程
- 第一次挥手: 客户端发送连接关闭报文(此时已经停止了发送数据)
- 报文首部: FIN = 1 (序列号seq=u)
- 此刻客户端进入FIN-WAIT-i状态,即终止等待
- 第二次挥手: 服务端向客户端发送确认报文
- 报文首部: ACK=1 ack=u+1(确认FIN) (序列标号seq=v)
- 此刻,服务端进入CLOSE-WAIT状态,也叫半关闭状态.客户端没有数据要发送,但是服务器如果还要发送数据,客户端依然需要接受数据
- 第二次挥手: 客户端收到服务器确认的请求后,客户端进入终止等待2(FIN-WAIT-2)
- 第三次挥手: 服务器确认数据已经发送完毕后,向客户端发送连接关闭报文,服务器进入最后的确认状态(LAST-ACK)
- 报文首部: FIN=1 ACK=1 ack=u+1(确认上一次数据包) 序列号seq=w
- 第四次挥手: 客户端收到服务器的连接关闭报文后,发出接受确认报文 ,客户端进入时间等待状态(TIME-WAIT)
- 服务器收到客户端的确认报文后,进入CLOSE状态.服务器关闭TCP连接比客户端更加的快.
- 客户端等待2ML后,CLOSE.
关闭TCP的四次挥手总结
-
为什么是四次挥手
- 原因:第一次挥手的时候发送了FIN包,服务器接收到以后,表示客户端不再发送数据了,但还能接收数据。这时服务器先向客户端先发送确认包,并且确认自己是否还有数据没有发送给客户端,这个确认的阶段是CLOSE-WAIT,所以在终止等待1 (CLOSE-WAIT)的开始和结束需要各发送一个包,状态开始时向客户端发送的包是确认收到来自客户端的FIN包,状态结束时向客广端发送的是确认数据已经完整发送,所以是四次挥手。
就是为了确认数据传输已经完成,所以需要服务器传两次状态.
-
TCP连接建立后,客户端突然出现故障?
-
TCP保活计时器:客户端如果出现故障,服务器每收到一次客户端的请求后都会重新复位保活计时器,时间通常是2小时,若2小时还没有收到客户端的数据,服务器就会发送一个探测报文段,以后每隔75分钟发送一次。若一连发送10个探测报文仍无反应,服务器就认为客户端出了故障,此时将关闭连接。
-
转载自:https://juejin.cn/post/7203717563238105143