TCP协议
# TCP协议
# TCP协议
# TCP报文头格式
源端口和目的端口字段
- TCP源端口(Source Port):源计算机上的应用程序的端口号,16位。
- TCP目的端口(Destination Port):目标计算机的应用程序端口号,16位。
序列号字段
Sequence Number:32位。它表示本报文段锁发送数据的第一个字节的编号。在TCP连接中,所传送的字节流的每一个字节都会按顺序编号。当SYN标记不为1时,这是当前数据分段第一个字母的序列号;如果SYN的值是1时,这个字段的值就是初始序列值(ISN),用于对序列号进行同步。这时,第一个字节的序列号比这个字段的值大1,也就是ISN加1。
确认号字段
Acknowledgment Number,ACK:32位。它表示接收方希望收到发送方下一个报文段的第一个字节数据的编号。其值就是接收计算机即将接收到的下一个序列号,也就是下一个接收到的字节的序列号加1.
保留字段
4位,必须全为0。
标志位字段
- CWR(Congestion Window Reduce):拥塞窗口减少标志,用来表明它接收到了设置 ECE 标志的 TCP 包。并且,发送方收到消息之后,通过减小发送窗口的大小来降低发送速率。
- ECE(ECN Echo):用来在 TCP 三次握手时表明一个 TCP 端是具备 ECN 功能的。在数据传输过程中,它也用来表明接收到的 TCP 包的 IP 头部的 ECN 被设置为 11,即网络线路拥堵。
- URG(Urgent):表示本报文段中发送的数据是否包含紧急数据。URG=1 时表示有紧急数据。当 URG=1 时,后面的紧急指针字段才有效。
- ACK:表示前面的确认号字段是否有效。ACK=1 时表示有效。只有当 ACK=1 时,前面的确认号字段才有效。TCP 规定,连接建立后,ACK 必须为 1。
- PSH(Push):告诉对方收到该报文段后是否立即把数据推送给上层。如果值为 1,表示应当立即把数据提交给上层,而不是缓存起来。
- RST:表示是否重置连接。如果 RST=1,说明 TCP 连接出现了严重错误(如主机崩溃),必须释放连接,然后再重新建立连接。
- SYN:在建立连接时使用,用来同步序号。当 SYN=1,ACK=0 时,表示这是一个请求建立连接的报文段;当 SYN=1,ACK=1 时,表示对方同意建立连接。SYN=1 时,说明这是一个请求建立连接或同意建立连接的报文。只有在前两次握手中 SYN 才为 1。
- FIN:标记数据是否发送完毕。如果 FIN=1,表示数据已经发送完成,可以释放连接。
窗口大小字段
Window Size:16位。它表示从 Ack Number 开始还可以接收多少字节的数据量,也表示当前接收端的接收窗口还有多少剩余空间。该字段可以用于 TCP 的流量控制。
TCP校验和字段
校验位(TCP Checksum):占 16 位。它用于确认传输的数据是否有损坏。发送端基于数据内容校验生成一个数值,接收端根据接收的数据校验生成一个值。两个值必须相同,才能证明数据是有效的。如果两个值不同,则丢掉这个数据包。Checksum 是根据伪头 + TCP 头 + TCP 数据三部分进行计算的。
紧急指针字段
紧急指针(Urgent Pointer):仅当前面的 URG 控制位为 1 时才有意义。它指出本数据段中为紧急数据的字节数,占 16 位。当所有紧急数据处理完后,TCP 就会告诉应用程序恢复到正常操作。即使当前窗口大小为 0,也是可以发送紧急数据的,因为紧急数据无须缓存。
可选项字段
选项(Option):长度不定,但长度必须是 32bits 的整数倍。
# TCP的特点
- 面向连接的运输层协议;
- 点对点,每一条TCP连接只能由两个端点;
- TCP提供可靠的服务;
- TCP提供全双工通信;
- 面向字节流。
# TCP的可靠传输
- 校验和:是一个端到端的校验和,由发送端计算,由接收端验证。其目的是发现TCP首部和数据在传输过程中是否发生改动。如果接受方检测到校验和有差错,则TCP段会被直接丢弃。
- 序列号:TCP给发送的每一个包进行编号,接受方对数据包进行排序,把有序数据传送给应用层。重复的数据丢弃。
- 确认应答:TCP传输过程中,每次接收方收到数据后,都会对发送方进行确认应答。也就是发送ACK报文。这个ACK报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。
- 超时重传:当TCP发出一个段后,它启动一个定时器,等待接收方确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
- 流量控制:由于发送方发送速度太快,导致接收方缓冲区很快填满,就会出现丢包、超时重传等问题。所以,当接受发方不及处理发送方的数据,能提示发送方降低发送速率,防止包丢失。TCP使用的流量控制协议是可变大小的滑动窗口协议。
- 拥塞控制:当网络拥堵时,应控制发送方的速率,与流量控制很像,流量控制是为了让接收方来得及接收,而拥塞控制是为了降低整个网络的拥塞程度。采用慢开始、拥塞避免、快重传、快恢复的控制。
- 连接管理:三次握手和四次挥手
# 三次握手
开始时客户端和服务器的状态都是CLOSED,然后服务器打开监听端口进入LISTEN状态。
- 客户端随机生成一个起始序列号x,向服务器发起建立连接的请求,发送的字段包含标志位SYN=1,序列号seq=x。客户端的状态从CLOSE变为SYN-SENT。
- 服务器在收到客户端发来的报文后,会随机生成一个服务端的起始序列号y,然后给客户端回复一段报文,其中包括标志位SYN=1,ACK=1,序列号seq=y,确认号ack=x+1。(SYN=1表示要和客户端建立一个连接,ACK=1表示确认序号有效),服务器状态从LISTEN变为SYN-RCVD。
- 客户端收到服务器发来的报文后,会再向服务器发送报文,其中包含标志位ACK=1,序列号seq=x+1,确认号ack=y+1。客户端状态从SYN-SENT变为ESTABLISHED。此时建立完成。
三次握手目的:保证双方都有发送和接受的能力,防止已失效的连接请求报文传输到服务器产生问题。
第一次握手的目的:服务器知道客户端具有发送数据的能力。
第二次握手的目的:客户端知道服务器具有发送和接收数据的能力。
第三次握手的目的:服务器知道客户端具有接收数据的能力。
# 不使用两次握手的原因
三次握手主要为了防止已失效的连接请求报文段突然又传输到服务端,导致产生问题。
比如,A 给 B 发送消息请求进行连接,由于网络原因阻塞在某个节点。由于阻塞的时间超过设定的重发时间,那么 A 就认为消息丢失了,然后重新发送消息请求连接,这次通讯连接成功,A 与 B 完成了通讯。过了一段时间,之前堵塞的消息被 B 接收到,B 以为这是一个新的请求连接,但对于 A 来说这是之前失效的消息,B 发了一个确认连接的消息给 A,A 收到后,认为他没有给 B 发送消息请求连接,就没有理睬B的确认消息,但是 B 认为它已经与A之间建立了连接,就在那里傻傻的等待,白白浪费 B 服务器的 CPU、内存等资源。
如果不采用三次握手,只要 B 发出确认,就建立了新的连接,此时 A 不会响应 B 的确认也不会发送数据,则 B 一直等待 A 发送数据,浪费资源。
# 四次挥手
在建立连接的时候,当服务器收到客户端的建立连接的请求报文后,可以直接发送确认建立连接的报文。但是在关闭连接时,当服务器端收到客户端发出的连接释放报文时,很可能并不会立即关闭,因为还有一些数据要发送,所以先回复收到,等服务器端的所有报文都发送完后再释放连接。
- A的应用进程先向B发出连接释放报文段(标志位FIN=1,序列号seq=u),并停止发送数据,进入FIN-WAIT-1终止等待1状态,等待B确认。
- B收到连接释放报文段后即发送确认报文段(标志位ACK=1,确认号ack=u+1,序列号seq=v),B进入关闭等待状态,此时TCP处于半关闭状态。A接收到报文后进入终止等待状态2,等待B发送连接释放报文段。
- B发送完数据,就会发出连接释放报文段(标志位FIN=1,ACK=1,序列号seq=w,确认号ack=u+1),B进入最后确认状态,等待A的确认。
- A收到B的连接释放报文后,对此发出确认报文(标志位ACK=1,序列号seq=u+1,ack=w+1),A进入时间等待状态。此时TCP未释放掉,需要等待2MSL(最大报文生存时间)后,A才进入CLOSED状态。B收到A发送的确认报文段后关闭连接,若没收到A发送的确认报文段,B就会重新发送释放连接报文。
# 四次挥手等待2MSL的原因
MSL:Maximum Segment Lifetime,最长报文段寿命
保证 A 发送的最后一个 ACK 报文能够到达 B
因为 A 发送的「确认报文」可能会丢失, B 未收到这个确认报文就会超时重传「连接释放报文」,只有当 A 未关闭,A 才可以收到这个重传的「连接释放报文」。A 重新发送确认报文再重新计时,确保 B 接收到了「确认报文」,最后 A 和 B 都进入关闭状态。如果不等待 2MSL,即 A 发送完「确认报文」后立即释放连接,若此时 B 未收到这个「确认报文」, B 将超时重传「连接释放报文」,但 A 已关闭连接无法收到,B 再也收不到来自 A 的「确认报文」,将无法进入到关闭状态。
防止已失效的连接请求报文段出现在新的连接中
A在发送完最后一个确认关闭报文后,在经过 2MSL,就可以使这个连接收产生的所有报文段都从网络中消失,使下一个新的连接中不会出现旧的连接请求报文。
为什么是 2MSL 呢?
- 当 B 发送「连接释放报文」后,如果 A 接收到了(以 A 接收到的这个时间节点为 0),就会在 MSL 时间内返回,也就是 B 应该在 MSL 时间内接收到「确认报文」。
- 但是 B 没有接收到,所以 B 在 MSL 这个时间点再次发送连接释放请求,这个请求会在 MSL 时间内到达 A,之前超时的 MSL,加上刚刚传输过程用的最长时间 MSL,所以共 2MSL。
# TCP与UDP
# TCP和UDP的区别
- TCP面向连接;UDP是无连接的,即发送数据时不需要建立连接。
- TCP提供可靠的服务;UDP不保证可靠交付。
- TCP面向字节流,把数据看成一串无结构的字节流;UDP是面向报文的。
- TCP有拥塞控制;UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如视频会议)
- 每一条TCP只能是点到点的;UDP支持一对一、一对多、多对一和多对多的通信方式。
- TCP首部开销20字节;UDP的首部开销少,只有8个字节。
# TCP和UDP的应用场景
- TCP:一般用于文件传输、发送和接收邮件、远程登录
- UDP:一般用于即时通信,比如:QQ聊天、在线视频、语音电话、广播