TCP理论基础

什么是TCP

传输控制协议TCP简介:

1、面向连接的、可靠的、基于字节流的传输层通信协议

2、将应用层的数据流分割成报文段并发送给目标节点的TCP层

3、数据包都有序号(seq),对方收到则发送ACK确认,未收到则重传

4、使用校验和来检验数据在传输过程中是否有误

OSI七层模型与tcp协议族

模型以及协议2

网络中的数据传输过程

数据传输封装过程

TCP报文头详解:

报文头

源端口:

​ 指定了发送端的端口

目的端口:

​ 指定了接受端的端口号

序号(Seq 4个字节):

​ 指明了段在即将传输的段序列中的位置

​ 假如序列号字段是108 携带的数据有100个字段,下一个报文序列号就是(108+100)也就是208开始

确认号(Ack):

​ 规定成功收到段的序列号,确认序号包含发送确认的一端所期望收到的下一个序号

​ 假设B收到A发来的报文,其序列号是301 数据长度是200字节 ,那么B期望收到A的下个序号是501,那么B发给A的确认报文ack就是501

TCP偏移量(offset):

​ 指定了段头的长度。段头的长度取决与段头选项字段中设置的选项,tcp报文数据距离 tcp报文起始处有多远

保留(reserved):

​ 指定了一个保留字段,以备将来使用

标志(TCP Flags):

SYN: 表示同步

 ACK: 表示确认

  PSH: 表示尽快的将数据送往接收进程

 RST: 表示复位连接

  URG: 表示紧急指针

  FIN: 表示发送方完成数据发送

窗口(window):

​ 滑动窗口大小,用来告知发送端和接收端的缓存大小,以此达到数据传输的速率控制,以此达到流量控制。指定关于发送端能传输的下一段的大小的指令

校验和(checksum):

​ 奇偶校验,校验和包含TCP段头和数据部分,用来校验段头和数据部分的可靠性

​ 由发送端计算和存储,由接收端验证

紧急指针:

​ 指明段中包含紧急信息,只有当U R G标志置1时紧急指针才有效

选项:

​ 指定了公认的段大小,时间戳,选项字段的末端,以及指定了选项字段的边界选项

TCP滑动窗口

RTT和RTO

>RTT∶发送一个数据包到收到对应的ACK,所花费的时间

>RTO∶重传时间间隔(规定时间内没有收到ack的时间就会重传),这个值根据RTT计算而来

QQ截图20211214231420

QQ截图20211214231517

TCP三次握手

TCP三次握手

在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。

第一次握手∶建立连接时,客户端发送SYN包(seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;

第二次握手∶服务器收到SYN包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手∶客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED 状态,完成三次握手。

Q:为什么需要三次握手才能建立起连接?

为了初始化Sequence Number的初始值

三次握手的核心就是交换seq,ack=seq+1表示交换seq成功

通信的双方要通知对方自己的seq序号,是作为以后数据通信的序号,保证数据不会因为网络上的传输问题而乱序,tcp会通过找个序号来拼接数据

Q:首次握手的隐患——SYN超时

SYN超时问题起因分析

> Server收到Client的SYN,回复SYN-ACK的时候未收到ACK确认

> Server不断重试直至超时(默认重复5次),Linux默认等待(1+2+4+8+16+32)=63秒才断开连接

针对SYN Flood的防护措施

> SYN队列满后,通过tcp_syncookies参数回发SYN Cookie

> 若为正常连接则Client会回发SYN Cookie,直接建立连接

Q:建立连接后,Client出现故障怎么办保活机制

向对方发送保活探测报文,如果未收到响应则继续发送

尝试次数达到保活探测数仍未收到响应则中断连接

TCP四次挥手

四次挥手

TCP采用四次挥手来释放连接

第一次挥手∶ Client发送一个FIN,用来关闭Client 到Server 的数据传送,Client进入 FIN_WAIT_1状态;

第二次挥手∶Server收到FIN后,发送一个ACK给 Client,确认序号为收到序号+1(与SYN 相同,一个FIN 占用一个序号),Server进入 CLOSE_WAIT状态;

第三次挥手∶Server 发送一个FIN,用来关闭Server 到 Client 的数据传送,Server进入 LAST_ACK状态;

第四次挥手∶Client收到 FIN后,Client进入TIME_WAIT 状态,接着发送一个ACK给 Server,确认序号为收到序号+1,Server进入 CLOSED状态,完成四次挥手。

Q:为什么会有TIME_WAIT状态?

确保有足够的时间让对方收到ACK包 数据以来一回就是2个MSL

避免新旧连接混淆

假设最终的ACK丢失,server将重发FIN,client必须维护TCP状态信息以便可以重发
最终的ACK,否则会发送RST,结果server认为发生错误。TCP实现必须可靠地终止连
接的两个方向(全双工关闭),client必须进入 TIME_WAIT 状态,因为client可能面
临重发最终ACK的情形。

Q:为什么服务器出现大量CLOSE_WAIT状态?

原因是对方关闭socket连接,我方忙于读或写,没有及时关闭连接

> 检查代码,特别是释放资源的代码(未释放资源)

> 检查配置,特别是处理请求的线程配置(线程池中的线程数配置不合理)

linux查看服务器close_wait状态语句

获取当前服务器处于各个状态下的连接数

netstat -n | awk '/^tcp/{++S[$NF]}END{for(a in S) print a,S[a]}'

TIME_WAIT 1507
CLOSE_WAIT 588
FIN_WAIT 2 5
ESTABLISHED 413

CLOSE_WAIT 如果有几千的话就要去排查问题了,linux会为用户提供有限的文件句柄数,链接和文件句柄是一一对应的,也就是说会无法处理新的请求,请求坑位没有了。新的请求无法被处理

Q:为什么需要四次握手才能断开连接?

因为全双工,发送方和接收方都需要FIN报文和ACK报文

原文地址:https://www.cnblogs.com/yslu/p/15690152.html