传输层协议UDP、TCP
- 一、TCP/UDP的任务
- 二、UDP
- 1.UDP概述
- 2.UDP报文格式
- 3.使用UDP的应用层协议
- 三、TCP
- 1.TCP概述
- 2.TCP报文
- 3.TCP三次握手
- 4.四次挥手
- 5.超时重传
- 6.流量控制和快重传
- 7.拥塞控制
- 8.延迟应答、捎带应答
- 9.粘包问题
- 10.基于TCP的应用层协议
- 四、总结
一、TCP/UDP的任务
我们在应用层调用网络相关的发送用户数据的接口时,本质不是直接把数据发送到网络中,而是把数据先拷贝到TCP/UDP的缓冲区里,而什么时候往网络里发送数据,发送多少数据,出错了怎么办的这些问题就是传输层协议要解决的。
二、UDP
1.UDP概述
用户数据报协议—UDP是传输层的协议,主要特点是:
- 无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接。
- 不可靠: 没有确认机制, 没有重传机制。 如果因为网络故障数据没有发送到对方, UDP协议层也不会给应用层返回错误信息。
- 面向数据报: 应用层交给UDP多长的报文, UDP就发送多长的报文,不会拆分和合并。
UDP的缓冲区:
UDP没有真正意义上的发送缓冲区:
调用sendto时数据直接交给内核, 由内核将数据传给网络层协议进行后续的传输动作
UDP具有接收缓冲区:
接收缓冲区不能保证收到的UDP数据报顺序和发送顺序一致; 如果缓冲区满了, 再到达的UDP数据报就会被丢弃
2.UDP报文格式
长度:数据报的长度,最小为8字节(只有报头),最大是64K,如果传输的数据超过64K, 需要在应用层手动的分包, 多次发送, 并在接收端手动拼装
校验值:检测UDP数据报是否有错,有错就丢弃
3.使用UDP的应用层协议
三、TCP
1.TCP概述
TCP,大名鼎鼎的传输控制协议,其主要特点如下:
- ⾯向连接:应用程序在使用TCP前要先建立TCP连接,数据传送完毕要释放建立好的TCP连接。
- 可靠的:通过TCP协议传输的数据无差错、不丢失、不重复、按序到达。
- 面向字节流:
字节流形式的数据 “没有边界”,消息多⼤都可以进⾏传输,如果应用层拷贝到TCP缓存的数据太长,TCP可以把数据划分的短一些构成多个报文传送,如果数据太少,TCP可以等数据较多时再构成报文发出去。
2.TCP报文
TCP报文格式如下:
序列号:
TCP连接中传送的每一个字节都按顺序编号
在建⽴连接时,设置整个要传送的字节流的起始序号为计算机⽣成的随机数
序列号则是本报文段发送的数据的第一个字节的序号
确认号:
是期望收到对方下一个报文段的序列号,而且若确认号为N,表明到N-1为止的数据都已正确收到
首部长度:
表示该TCP头部有多少个32位bit(有多少个4字节);
因为是4位,表示的最大二进制数是15,所以TCP头部最大长度是15 * 4 = 60
最小是固定的20字节
窗口大小:
表明自己接收缓冲区剩余的空间大小,要求对方发送数据时必须考虑到这一点,这个值通常是动态变化的。
校验和:
校验的范围包括首部和数据
发送端填充CRC校验。接收端校验不通过, 则认为数据有问题
紧急指针:
指出了紧急数据的末尾在报文段中的位置
六位标志位:
URG: 为1代表紧急指针有效
ACK: 为1代表有效,连接建立后所有的报文ACK都为1
PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
RST: 表明出现严重差错,必须释放连接重新建立
SYN: 为1代表这是一个连接请求(SYN=1,AVK=0)
或连接接受报文(SYN=1,AVK=1)
FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段
3.TCP三次握手
⼀开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端⼝,处于 LISTEN 状态
客户端会随机初始化序号( client_isn ),将此序号置于 TCP ⾸部的「序号」字段中,同时把 SYN 标志位置为 1 ,接着把SYN报⽂发送给服务端,表示向服务端发起连接,该报⽂不包含应⽤层数据,之后客户端处于 SYN_SENT 状态。
服务端收到客户端的 SYN 报⽂后,⾸先也随机初始化⾃⼰的序号( server_isn ),将此序号填⼊TCP ⾸部的「序号」字段中,其次把 TCP ⾸部的「确认应答号」字段填⼊ client_isn + 1 , 接着把 SYN和 ACK 标志位置为 1 。最后把该报⽂发给客户端,该报⽂也不包含应⽤层数据,之后服务端处于 SYN_RCVD 状态。
客户端收到服务端报⽂后,还要向服务端回应⼀个应答报⽂,⾸先该应答报⽂ TCP ⾸部 ACK 标志位置为 1 ,其次「确认应答号」字段填⼊ server_isn + 1 ,最后把报⽂发送给服务端,这次报⽂可以携带客户到服务器的数据,之后客户端处于 ESTABLISHED 状态。服务器收到客户端的应答报⽂后,也进⼊ ESTABLISHED 状态。此时连接就已建⽴完成,客户端和服务端就可以相互发送数据了。
4.四次挥手
客户端打算关闭连接,此时会发送⼀个 TCP ⾸部 FIN 标志位被置为 1 的报⽂,也即 FIN 报⽂,之后客户端进⼊ FIN_WAIT_1 状态。
服务端收到该报⽂后,就向客户端发送 ACK 应答报⽂,接着服务端进⼊ CLOSED_WAIT 状态。
客户端收到服务端的 ACK 应答报⽂后,之后进⼊ FIN_WAIT_2 状态。
等待服务端处理完数据后,也向客户端发送 FIN 报⽂,之后服务端进⼊ LAST_ACK 状态。
客户端收到服务端的 FIN 报⽂后,回⼀个 ACK 应答报⽂,之后进⼊ TIME_WAIT 状态。
服务器收到了 ACK 应答报⽂后,就进⼊了 CLOSED 状态,⾄此服务端已经完成连接的关闭。
客户端在经过 2MSL ⼀段时间后,⾃动进⼊ CLOSED 状态,⾄此客户端也完成连接的关闭。
5.超时重传
TCP的发送方在规定时间内没有收到确认报文就要重传已发送的报文。
没有收到确认报文可能是发送方的发送报文丢失,也可能是确认报文丢失,如果是确认报文丢失进行了超时重传,接收方会收到一些重复的报文,TCP协议利用前面提到的序列号识别出重复的包, 并且丢弃。
TCP为了保证高性能通信, 动态计算这个最大超时时间。
Linux中(BSD Unix和Windows也是如此), 超时以500ms为一个单位进行控制, 每次判定超时重发的超时
时间都是500ms的整数倍。
如果重发一次之后, 仍然得不到应答, 等待 2500ms 后再进行重传。
如果仍然得不到应答, 等待 4500ms 进行重传,以此类推, 以指数形式递增。
累计到一定的重传次数, TCP认为网络或者对端主机出现异常, 强制关闭连接。
6.流量控制和快重传
上文解释过窗口的含义,还有一个概念是滑动窗口
滑动窗口其实是发送缓冲区的一部分(实际上缓冲区是头尾相接的环形):
假设A收到了B发来的确认报文,窗口是20字节,确认号是31,根据这两个数据A构造出自己的发送窗口如图
在没有收到B的确认报文的情况下,允许A可以把滑动窗口里的数据都发出去,但是在A收到B的确认报文前,发送出去的数据都要暂时保留在滑动窗口里,以便超时重传时使用。
显然,A的发送窗口里的数据量不能超过B的接收能力。
发送窗口的大小由前沿和后沿决定。窗口越大, 则网络的吞吐率就越高。
收到新确认,后沿就可以前移,没有收到,后沿不动。
前沿通常向前移动,但是由于接收方接受能力变低,前沿也可能不动。
前沿也可能向后收缩,但TCP标准强烈不赞成这样做
滑动窗口既保证了发送方的效率,又考虑了接收方的接受能力,这就是所谓的流量控制,这种机制从三次握手期间就开始了。
那如果丢包了怎么处理?
分两种情况
上图这种情况,ACK600丢失,但不需要重传,因为后续的ACK700被发送方收到
还有一种情况是发送方的报文丢失
那么发送方会一直连续收到接收方发来相同的ACK,连续收到三个就重新发送对应的报文,这种机制被称为 “高速重发控制”,也叫 “快重传”。
7.拥塞控制
⼀般,一个计算机⽹络都是很多主机共享的。因此可能会因为其他主机之间的通信使得⽹络拥堵。在⽹络拥堵时,如果发送⼤量数据包,可能会导致数据包时延、丢失,这时 TCP 会重传数据,但是重传就会导致⽹络的负担更重,这就需要拥塞控制。
拥塞控制简单说就是⽹络发送拥塞时,TCP 会减少发送的数据量,为了在发送⽅调节发送数据量,定义了拥塞窗⼝的概念。拥塞窗⼝也是发送⽅的窗口,它会根据⽹络的拥塞程度动态变化。发送窗口的大小实际上是拥塞窗⼝和接收窗⼝中的最⼩值。
拥塞窗⼝变化的规则:
只要⽹络中没有出现拥塞, 拥塞窗口变⼤;
⽹络中出现了拥塞, 窗口变小;
拥塞控制过程:
拥塞窗口大小开始为1,一开始是慢启动算法,呈指数增长,当窗口大小超过慢启动阈值(ssthresh), 不再按照指数方式增长, 而是按照线性方式增长。当网络拥塞,发生超时重传或快重传后需要重置拥塞窗口大小和慢启动阈值。
例如:
发生快重传时:
例如:
8.延迟应答、捎带应答
延迟应答:
如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小。
假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K;
但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了;
在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;
如果接收端稍微等一会再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M;
窗口越大, 网络吞吐量就越大, 传输效率就越高。
不是所有的包都可以延迟应答
数量限制: 每隔N个包就应答一次
时间限制: 超过最大延迟时间就应答一次
具体的数量和超时时间, 依操作系统不同也有差异; 一般N取2, 超时时间取200ms
捎带应答:
9.粘包问题
首先要明确, 粘包问题中的 “包” , 是指的应用层的数据包!
TCP是基于字节流的,只维护发送出去多少,确认了多少,并没有维护消息与消息之间的边界,这就导致了粘包问题。
可参考这里🔗
10.基于TCP的应用层协议
四、总结
对比TCP/UDP
UDP 在传送数据之前不需要先建立连接,远端收到 UDP 报文后,不需要给出任何确认。虽然 UDP 不提供可靠交付,但在某些情况下 UDP 却是一种最有效的工作方式(一般用于即时通信),比如: QQ 语音、 QQ 视频 、直播等等
TCP 在传送数据之前必须先建立连接,数据传送结束后要释放连接。TCP 为了提供可靠的,面向连接的传输服务,采用了很多机制,同时就增加了时间和空间的开销。所以TCP报文首部也比UDP复杂,还要占用许多处理机资源。TCP 一般用于文件传输、发送和接收邮件、远程登录等场景。
TCP和UDP都是传输使用的工具, 什么时机用, 具体怎么用, 还是要根据具体的需求场景去判定
本文部分内容参考自
《计算机网络》 谢希仁
《图解网络》 小林