目录
1、TCP报头
1、源端口(16bit):标识报文的返回地址
2、目的端口(16bit):指明接收方的应用程序接口
TCP报头中的源端口号和目的端口号同IP数据报中的源IP与目的IP唯一确定一条TCP连接。
3、序列号(32bit):序列号确定了发送方发送的数据流中被封装的数据所在的位置
4、确认应答号(32bit):确认号确定了源点下一次希望从目标接收到的序列号,如果接受到的确认号与它下一次打算发送的序列号不符,主机将知道丢失的数据包
5、头部长度(4bit):也叫数据偏移,指示了数据区在报文段中的起始偏移值,TCP头的长度是一个32位的整数倍。
6、Flag位
-
保留位(6bit)
-
URG(紧急):标识紧急指针是否有效
-
ACK(确认):标识确认序号是否有效
-
PSH(弹出):用来提示接收端应用程序立刻将数据从TCP缓冲区读走
-
RST(复位):要求重新建立连接
-
SYN(同步):请求建立连接
-
FIN(结束):通知对端, 本端即将关闭
7、窗口大小(16bit):用来告知发送端接收端的缓存大小,以此控制发送端发送数据的速率,达到流量控制
8、校验和(16bit):奇偶校验,针对整个TCP报文,由发送端计算和存储,接收端验证
9、紧急指针(16bit):只有当URG标志置1才有效
10、可选项(0或32bit):最常见的可选字段是最长报文大小MSS(Maximun Segement Size),选项长度不一定是32的整数倍,所以要添加填充位,即在这个字段中加入额外的0,以保证TCP头是32的整数倍。
MSS(Maximun Segement Size)=MTU-TCP头部-IP头部
2.1、 什么是TCP:
传输控制协议TCP (Transmission Control Protocol)
面向连接的、可靠的(ACK)、基于字节流的、有序的(SYN序列号)、流量控制(滑动窗口)的传输控制协议。
面向连接:一定是「一对一」才能连接,不能像 UDP 协议可以一个主机同时向多个主机发送消息,也就是一对多是无法做到的;
可靠的:无论的网络链路中出现了怎样的链路变化,TCP 都可以保证一个报文一定能够到达接收端;
字节流:用户消息通过 TCP 协议传输时,消息可能会被操作系统「分组」成多个的 TCP 报文,如果接收方的程序如果不知道「消息的边界」,是无法读出一个有效的用户消息的。并且 TCP 报文是「有序的」,当「前一个」TCP 报文没有收到的时候,即使它先收到了后面的 TCP 报文,那么也不能扔给应用层去处理,同时对「重复」的 TCP 报文会自动丢弃。
2.2、什么是TCP连接
我们来看看 RFC 793 是如何定义「连接」的:
Connections: The reliability and flow control mechanisms described above require that TCPs initialize and maintain certain status information for each data stream. The combination of this information, including sockets, sequence numbers, and window sizes, is called a connection.
简单来说就是,用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括 Socket、序列号和窗口大小称为连接。
所以,建立一个 TCP 连接是需要客户端与服务端达成以下三个信息的共识:
-
Socket:由 IP 地址和端口号组成
-
序列号:用来解决乱序问题等
-
窗口大小:用来做流量控制
3、TCP三次握手建立连接
(1) 三次握手建立连接的目的:协商参数(协商序列号、窗口初始化)
(2) 三次握手
-
第一次握手:Client将标志位SYN置为1,随机产生一个值seq=x,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认
-
第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=x+1,随机产生一个值seq=y,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态
-
第三次握手:Client收到确认后,检查ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=y+1,并将该数据包发送给Server,Server检查ack是否为y+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了
第三次握手是可以携带数据的,前两次握手是不可以携带数据的
CLOSED:初始状态,表示TCP连接是”关闭着的”或”未打开的”
LISTEN:表示服务器端的某个SOCKET处于监听状态,可以接受客户端的连接
SYN_RCVD:表示服务器接收到了来自客户端请求连接的SYN报文。这个状态是在服务端的,但是它是一个中间状态,很短暂,平常我们用netstat或ss的时候,不太容易看到这种状态。但是遇到SYN flood之类的SYN攻击时,会出现大量的这种状态,即收不到三次握手最后一个客户端发来的ACK,所以一直是这个状态,不会转换到ESTABLISHED
SYN_SENT:这个状态与SYN_RCVD状态相呼应,,它是TCP连接客户端的状态,当客户端SOCKET执行connect()进行连接时,它首先发送SYN报文,然后随机进入到SYN_SENT状态,并等待服务端的SYN和ACK,该状态表示客户端的SYN已发送
ESTABLISHED:表示TCP连接已经成功建立,开始传输数据
以上就是三次握手的五种TCP状态,单从客户端服务端角度来区分的话,CLOSED和ESTABLISHED会在客户端和服务端都出现,而LISTEN和SYN_RCVD通常是出现在服务端,SYN_SENT出现在客户端
但通常在服务器和客户端并不是绝对的,比如 Nginx 的服务器中,Nginx 通常作为 web 代理服务器,它既是服务端,也是客户端,所以在查询统计 TCP 状态的时候,最好通过匹配端口来区分是客户端的还是服务端的,来更精确的定位问题。
4、TCP四次挥手拆除连接
(1) 四次挥手拆除连接的目的:释放资源,回收序列号
(2) 四次挥手
-
第一次挥手:Client发送一个FIN=1,随机产生一个值seq=u,用来关闭Client到Server的数据传送,Client进入FIN_WAIT-1状态
-
第二次挥手:Server收到FIN=1后,发送一个ACK给Client,随机产生一个值seq=v,确认序号为收到序号u+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态
-
第三次挥手:Server发送一个FIN=1,ACK=1,随机产生一个值seq=w,确认序号为u+1,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态
-
第四次挥手:Client收到FIN=1后,Client进入TIME_WAIT状态,接着发送一个ACK=1,seq=u+1给Server,确认序号为w+1,Server进入CLOSED状态,完成四次挥手
FIN_WAIT_1:这个状态在实际工作中很少能看到,当客户端想要主动关闭连接时,它会向服务端发送FIN报文,此时TCP状态就进入到FIN_WAIT_1的状态,而当服务端回复ACK,确认关闭后,则客户端进入到FIN_WAIT_2的状态,也就是只有在没有收到服务端ACK的情况下,FIN_WAIT_1状态才能看到,然后长时间收不到ACK,通常会在默认超时时间60s(由内核参数tcp_fin_timeout控制)后,直接进入CLOSED状态
FIN_WAIT_2:这个状态相比较常见,也是需要注意的一个状态,FIN_WAIT_1在接收到服务端ACK之后就进入到FIN_WAIT_2的状态,然后等待服务端发送FIN,所以在收到对端FIN之前,TCP都会处于FIN_WAIT_2的状态。在主动断开的一端发现大量的FIN_WAIT_2状态时,需要注意,可能是网络不稳定或程序中忘记调用连接关闭。FIN_WAIT_2也有超时时间,也是由内核参数tcp_fin_timeout控制,当FIN_WAIT_2状态超时后,连接直接销毁
CLOSE_WAIT:表示正在等待关闭,该状态只在被动端出现,即当主动断开的一端调用close()后发送FIN报文给被动端,被动段必然会回应一个ACK(这是由TCP协议层决定的),这个时候,TCP连接状态就进入到CLOSE_WAIT
LAST_ACK:当被动关闭的一方在发送FIN报文后,等待对方的ACK报文的时候,就处于LAST_ACK的状态,当收到对方的ACK之后,就进入到CLOSED状态了
TIME_WAIT:该状态是最常见的状态,主动方在收到对方FIN后,就由FIN_WAIT_2状态进入到TIME_WAIT状态
CLOSING:这个状态是一个比较特殊的状态,也比较少见,正常情况下不会出现,但是当双方同时都作为主动的一方,调用 close() 关闭连接的时候,两边都进入FIN_WAIT_1 的状态,此时期望收到的是ACK包,进入 FIN_WAIT_2 的状态,但是却先收到了对方的FIN包,这个时候,就会进入到 CLOSING 的状态,然后给对方一个ACK,接收到 ACK 后直接进入到 CLOSED 状态。
5、TCP保证可靠性的机制
-
校验和
-
序列号
-
确认应答
-
超时重传
-
连接管理
-
流量控制
-
拥塞控制
6、提升性能的机制
(1) 滑动窗口
1) 作用
• 在网络传输时进行流量控制,避免网络拥塞
• 在发送端发送数据的速度很快而接收端接收速度很慢的情况下,为了保证数据不丢失,需要进行流量控制, 协调好通信双方的工作节奏
• 在停止并等待确认前发送多个数据分组,发送方不必每发一个分组都停下来等待确认,可以加速数据的传输,提高网络吞吐量
2) A与B之间建立TCP连接,滑动窗口实现有两个作用
-
B端来不及处理接收数据(控制不同速率主机间的同步),这时,A通过B端通知的接收窗口而减缓数据的发送
-
B端来得及处理接收数据,但是在A与B之间某处如C,使得AB之间的整体带宽性能较差,A端根据拥塞处理策略(慢启动,加倍递减和缓慢增加)来更新窗口,以决定数据的发送
(2)快速重传
1) 数据包接收到了,确认应答ACK丢失
-
可以通过后续的ACK来确认对方已经收到了哪些数据包
2) 数据包丢失
举例:当某一段报文丢失之后, 发送端会一直收到 1001 这样的ACK, 就像是在提醒发送端 “我想要的是 1001”,如果发送端主机连续三次收到了同样一个 “1001” 这样的应答,就会将对应的数据 1001 - 2000 重新发送,这个时候接收端收到了 1001 之后,再次返回的ACK就是7001了,因为2001 - 7000接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中
3)延迟应答
4)捎带应答
7、TCP连接建立的本质
两者告知彼此的第一个发送字节的初始序列号,建立连接后对每一个发送的字节都需要以初始序列号为原点进行编号,需要对方来确认每一个字节编号都已经成功接收,双方初始序列号是由 OS 动态生成的随机的值,一般每个 TCP session 都会有不一样的初始序列号,占四个字节
8、TCP通过序列号、确认应答和超时重传提高可靠性
-
在 TCP 中,当发送端的数据到达接收主机时,接收端主机会返回一个ACK告知发送端已经收到该数据;当发送端将数据发出之后会等待对端的确认应答,如果有确认应答,说明数据已经成功到达对端;反之,则数据可能丢失。
-
若在一定时间内没有等待到确认应答,发送端就可以认为数据已经丢失,并进行重发,由此,即使产生了丢包,仍然能够保证数据能够到达对端,实现可靠传输。
-
未收到确认应答并不意味着数据一定丢失,也有可能是数据对方已经收到,只是返回的确认应答在途中丢失,这种情况也会导致发送端误以为数据没有到达目的地而重发数据。
-
数据可能因为一些其他原因导致确认应答延迟到达,在源主机重发数据以后才到达的情况也屡见不鲜;此时,源主机只要按照机制重发数据即可。
-
对于目标主机来说,反复收到相同的数据是不可取的,为了对上层应用提供可靠的传输,目标主机必须放弃重复的数据包,引入了序列号保证了数据的可靠传输。
-
接收端查询接收数据 TCP 首部中的序列号和数据的长度,将自己下一步应该接收的序列号作为确认应答返送回去;通过序列号和确认应答号,TCP 能够识别是否已经接收数据,又能够判断是否需要接收,从而实现可靠传输。
9、TCP应用场景
TCP用于可靠传输的情况, 应用于文件传输, 重要状态更新等场景
- 高可靠性:需要传输数据完整性,无丢包、无错序。
- 顺序传输:数据按发送顺序到达接收端。
- 长时间连接:需要维持会话状态。
1. Web浏览
- 应用:HTTP/HTTPS协议
- 场景:访问网站、加载网页内容、浏览器与服务器之间的通信。
- 特点:
- 需要完整、准确地传输数据。
- 使用TCP来确保网页的HTML、CSS、JS、图片等内容按顺序到达。
2. 文件传输
- 应用:FTP、SFTP、FTPS等协议
- 场景:文件上传与下载。
- 特点:
- 确保文件数据不丢失、不重复。
- TCP提供可靠性保证,适合大文件传输。
3. 电子邮件
- 应用:SMTP(发送)、POP3、IMAP(接收)
- 场景:邮件发送、接收和同步。
- 特点:
- 邮件内容需要准确无误。
- TCP提供分段重组和错误校验。
4. 远程登录
- 应用:SSH、Telnet
- 场景:远程服务器管理、命令执行。
- 特点:
- 实时性要求较高。
- 需要数据传输的完整性与可靠性。
5. 数据库交互
- 应用:MySQL、PostgreSQL等数据库协议
- 场景:客户端与数据库服务器之间的数据查询与更新。
- 特点:
- 保证查询请求和响应的准确性。
- TCP确保事务的完整性和一致性。
6. 点对点文件共享
- 应用:基于TCP的P2P协议
- 场景:例如一些文件同步工具(如BitTorrent的一些扩展模式)。
- 特点:
- 需要可靠的连接,确保数据包的完整性。
7. 在线购物与支付
- 应用:基于HTTP/HTTPS的应用
- 场景:例如电商平台、支付系统。
- 特点:
- 必须保证订单和支付数据的完整性与安全性。
8. 消息传递
- 应用:XMPP(某些配置下)、邮件队列服务等
- 场景:例如需要确保消息顺序和内容的应用。
- 特点:
- TCP的可靠性适用于消息传递系统的核心部分。
总结:
- 高可靠性:需要数据传输完整性,无丢包、无错序。
- 有序传输:数据按发送顺序到达接收端。
- 长时间连接:需要维持会话状态。