TCP协议
TCP协议格式
1.源/目的端口号:用来表示数据从哪个进程过来,发送到哪个进程去。
2.32位序号 / 32位确认号:分别是TCP所携带的起始序号和期望对方从哪一个序号开始发送。
3.4位TCP报头长度:指的是TCP头部长度。
4.6位标志位:
- URG:紧急指针是否有效。
- ACK:确认号是否有效。
- PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走。
- RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段。
- SYN:请求建立连接;我们把携带SYN标识的称为同步报文段。
- FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段。
5.16位窗口大小:告知发送端接收端能接收的数据大小。
6.16位校验核:是一个端到端的校验,由发送端发送再由接收端验证。查看数据是否有改动
7.16位紧急指针:标识哪一些是紧急数据。
基于TCP的应用层协议
- HTTP
- HTTPS
- SSH
- Telnet
- FTP
- SMTP
TCP原理:TCP通过以下原理保证数据传输的安全可靠
确认应答机制(安全机制)
TCP每一个数据都带有一个编号,即为序列号,每一个ACK都带有一个确认序列号,意思是告诉发送方,下一个数据要从多少开始发
超时重传机制(安全机制)
情况1:
情况2:
连接管理机制(安全机制)
三次握手建立连接:
一次握手:客户端发送带有 SYN 标志的数据报给服务端,客户端进入 SYN_SEND 状态,等待确认。
二次握手:服务端发送带有 SYN + ACK 标志的数据报给客户端,服务端进入 SYN_RECV 状态。
三次握手:客户端发送带有 ACK 标志的数据报给服务端,最终客户端与服务端都进入 ESTABLISHED 状态。TCP 的三次握手完成。
为什么是三次握手,不是两次或者四次呢?
首先,第一次握手,客户端什么都无法确认,而服务端可以确认自己接收正常,客户端发送正常。
第二次握手,客户端可以确认自己接收也正常,服务端发送接收正常。而服务端也可以确认自己发送正常。
第三次握手,服务端最终确认客户端的接收正常。
即最终,客户端和服务端都确认自己的接收和发送以及对方的接收和发送都正常。只有三次握手能确认双方收发功能都正常,缺一不可。
四次握手断开连接:
第一次挥手:客户端发送一个带有 FIN 标志的数据报,请求服务端关闭连接,进入 FIN_WAIT1状态。
第二次挥手:服务端发送一个 ACK 标志的数据报给客户端,告知客户端已经接收到了关闭连接的请求。服务端进入 CLOSE_WAIT 状态,客户端进入 FIN_WAIT2 状态。
第三次挥手:服务端发送一个 FIN 标志的数据报给客户端,请求关闭连接,服务端进入 LAST_ACK 状态。
第四次挥手:客户端发送一个 ACK 给服务端,然后进入 TIME_WAIT 状态。服务端接收到 ACK 后进入 CLOSED 状态,客户端在 2MSL 后没有接收到任何消息后就证明服务端已经正常关闭,即客户端也可以关闭里。
只要四次挥手没有结束,客户端和服务端就可以继续传输数据。
为什么不能把第二次挥手和第三次挥手合并?
TCP 是全双工通信,可以双向传输数据。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了 TCP 连接。
因为服务端接收到客户端断开连接的请求时候,此时的数据可能还没有发送完成,这时候先发送 ACK,表示已经收到了断开连接的请求,等消息发送完再发送 FIN 请求关闭连接。
滑动窗口(效率机制)
了解了确认应答机制后,我们知道,每次发送一个数据报,都需要等待ACK,再发送下一个数据段,但是这样效率很低,于是就有如下图操作。
- 该滑动窗口的大小为4000。
- 发送前四个数据报的时候,不需要等待ACK,直接发送。
- 收到第一个ACK后,滑动窗口向后移动,发送第五个数据报,以此类推。
如果在该过程出现了丢包,该如何解决:
情况1:ACK丢失:如果只是部分ACK丢失,可以根据后续ACK确认,如下图所示
虽然前面两次ACK丢失,但是可以通过后面两次确认数据已经发送成功。
情况2:数据报丢失:
当一段数据报丢失后,主机B会一直发送下一个是2001的ACK给主机A,当主机A连续收到后就会重新发送1001-2000这一段数据报,然后主机B会直接返回下一个是4001,(因为前面的数据已经收到了)。
流量控制(安全机制)
流量控制是一种安全机制,因为接收端的处理速度是有限的。如果发送端发送的太快,导致接收端缓冲区被装满,继续发送就会导致丢包等一系列问题。所以 TCP 会根据接收端的处理数据速度来决定发送端的发送速度,这就是流量控制。
- 发送端口会定时发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。
- 接收端可以将自己缓冲区的大小放入 TCP 首部的 "窗口大小" 字段,通过 ACK 通知发送端。
- 发送端接收到这个信号时,就会减少发送的速度。
拥塞控制(安全机制)
虽然 TCP 已经拥有流量控制,但是如果在一开始就发送大量数据,在网路拥堵的时候,仍然可能出现丢包的问题。因此 TCP 引入了慢启动机制。
- 此处引入一个概念叫拥塞窗口。
- 初始的时候,拥塞窗口的大小为 1。
- 接下来,每次收到一个 ACK 请求,拥塞窗口的大小加 1。
- 每次发送窗口的大小取决于接收端反馈的大小和拥塞窗口大小的最小值。
- 由于拥塞窗口是指数增长的,为了使得拥塞窗口增长的没有那么快,引入一个概念叫做慢启动阀值,当拥塞窗口的大小达到慢启动阀值的时候,增长速度从指数变成线性方式增长。
- 初始时,慢启动阀值为窗口的最大值。
- 每次重传,慢启动阀值变为原来的一半,拥塞窗口大小变为零。
延时应答(效率机制)
如果接收端接收到数据立刻返回 ACK,会导致返回的窗口比较小,为了提高发送效率,就需要延时应答。
- 不是所有的包都要延时应答。
- 数量限制:每隔 N 个包延时应答一次(N一般为 2)。
- 时间限制:超过最大延时时间应答一次。
捎带应答(效率机制)
我们知道,在客户端的应用层数据也是一发一收的,如客户端给服务器发送了一条信息,那么服务器也会返回一条信息。这个时候 ACK 就可以搭顺风车,和服务器端的信息一起发送回给客户端,这就是捎带应答机制。
TCP面向字节流产生的问题:粘包问题
- 首先,这里的包指的是应用层的数据包。
- 由于 TCP 中没有像 UDP 那样的数据报文长度字段。
- 在传输层,TCP 是一个一个报文发送过来并按照序号存放在缓冲区中。
- 而在应用层看来,只是一连串的字节数据。
- 因此,应用层无法分辨哪一部分到哪一部分是一个完整的数据报。
那么如何解决粘包问题:
- 对于定长的包,每次按照固定大小读取即可。
- 对于变长的包,可以在包头位置约定一个包总长度字段。
- 对于变长的包,还可以在包和包之间添加分隔符。
UDP协议
UDP的报文结构
- 源端口:用于存放发送端的端口号。
- 目的端口:用于存放接收端的端口号。
- UDP长度:表示整个数据报的最大长度。
- 校检和: 接收方在传输数据时会记录下数据的“摘要”,等到数据传输到接收端时,会再次检查“摘要”是否与传输之前一致,如果不一致就会直接丢弃。
UDP协议的特点
- 无连接:已知接收端的端口号和 IP 就可以直接进行传输,无需建立连接。
- 不可靠:没有任何安全措施,发送端发送数据报如果发送失败,不会给应用层返回任何信息。
- 面向数据报:不会对数据报进行拆分和合并。
- 全双工:可以同时双向发送数据。
- 缓冲区:UDP 没有接收缓冲区,只有发送缓冲区。
基于UDP的应用层协议
- NFS:网络文件系统。
- TFTP:简单文件传输协议。
- DHCP:动态主机配置协议。
- BOOTP:启动协议(用于无盘设备启动)。
- DNS:域名解析协议。
UDP 和 TCP 的区别
- UDP 是无连接的,只需要知道端口号和 IP 就可以直接进行传输。而 TCP 是有连接的,发送数据前需要建立连接。
- UDP 是不可靠的,数据发送失败或者成功都不会返回任何的信息,而 TCP 是可靠的,有确认应答超时重传等安全机制保证数据传输的可靠性。
- UDP 只有发送缓冲区没有接收缓冲区,而 TCP 有接收缓冲区。
- UDP 的传输效率较高,实时性好,适用于如视频,直播等。而 TCP 传输效率低,但是可靠性高,适用于文件传输或者邮件传输等。