运输层和TCP/IP协议
0. 基本要点
- 运输层是为相互通信的应用进程提供逻辑通信。
- 端口和套接字的意义
- 什么是无连接UDP
- 什么是面向连接的TCP
- 在不可靠的网络上实现可靠传输的工作原理,停止等待协议和ARQ协议
- TCP的滑动窗口、流量控制、拥塞控制和连接管理
1. 运输层协议概述
- 为什么需要运输层?
通信真正的端点并不是主机而是主机中的进程,IP协议帮助我们将分组数据发送到对应的主机,但是这个分组还是停留在了网络层,IP协议并不知道需要将分组数据交付给主机中的哪一个应用或者哪一个进程,而运输层的作用在于,一方面为上层应用层提供进程的端到端通信服务,一方面屏蔽了下面网络核心的细节,在逻辑上好像两个进程实体之间存在一条端到端的逻辑通信通道。 - 运输层的两个功能:复用和分用
- 运输层和网络层的区别:
- 网络层为主机之间提供逻辑通信,运输层为进程之间提供端到端的逻辑通信
- 运输层还要对报文进行差错检测,网络层只检验头部部分
2. TCP和UDP
- UDP传输的是UDP报文段,在传送数据之前不需要建立连接
- TCP提供面向连接的服务,传送数据前要建立连接,传送结束后要释放连接,TCP 不提供广播和多播服务,因为TCP要保证可靠的连接,因此增加很多相应的开销,协议首部会相对较大,同时也占用很多处理机的资源
应用 | 应用层协议 | 运输层协议 |
---|---|---|
名字转换 | DNS(域名系统) | UDP |
文件传输 | TFIP(简单文件传输协议) | UDP |
路由选择协议 | RIP(路由协议信息) | UDP |
IP地址分配 | DHCP(动态主机配置地址) | UDP |
网络管理 | SNMP(简单网络管理协议) | UDP |
远程文件服务器 | NFS(网络文件系统) | UDP |
IP电话 | 专用协议 | UDP |
流式多媒体通信 | 专用协议 | UDP |
多播 | IGMP(网际组管理协议) | UDP |
电子邮件 | SMTP(简单邮件传输协议) | TCP |
远程终端接入 | TElNET(远程终端协议) | TCP |
万维网 | HTTP(超文本传输) | TCP |
文件传输 | FTP(文件传输协议) | TCP |
- 端口:标志本计算机应用层的各个进程与运输层交互的层间接口,为了找到对方计算机中的应用进程。因为进程在不同的操作系统中的进程标识符是不同的,因此用标识符来识别进程是行不通的。
-
服务器使用的端口号:系统端口号:0-1023 登记端口号:1024-49151
常见端口号:FTP:21, TELNET:23, SMTP:25
DNS:55,TFTP:69,HTTP:80
SNMP:161 SMP(trap):162 ,HTTPS:443 -
客户端使用端口号:短暂端口号 49152-65535
-
3. UDP协议
- UDP是无连接的,UDP不需要维持复杂的连接状态表,它尽最大努力交付
- UDP是面向报文的,这里注意:UDP对于应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界,应用层交给UDP多长的报文,UDP就封装多长的报文,因此,用户需要选择合适的报文长度,否则交给IP层后,过长会导致分片,太短会造成首部相对长度太大,降低IP层的效率。
- UDP没有拥塞控制,网络拥塞不会降低源主机的发送效率。在一些实时应用中,如IP电话允许存在一定程度的丢包,但不允许太大延时。
- UDP支持一对一,一对多,多对多交互通信
- UDP首部开销小,只有8个字节,每个字段的长度都是两个字节,源端口+目的端口+长度+校验和
4. TCP协议
4.1 TCP协议特点
- TCP协议是面向连接的,使用时建立连接,使用完毕释放连接
- 每个TCP连接只有连个端点,也就是说TCP连接是点对点,一对一的
- TCP提供可靠的交付,无差错,不丢失,不重复,并且按序到达
- TCP提供全双工的通信,TCP允许进程任何时候都发送数据,TCP两端设有发送缓存和接收缓存,TCP会在合适的时候读取缓存或者将缓存中的数据发送出去。
- TCP面向字节流,注意TCP并不关心进程一次将多少缓存发送到TCP的缓存,UPD发送的报文长度由进程指定,而TCP则是根据对方给的窗口值和当前网络拥塞情况而决定一个报文段包含多少字节。如果缓存数据块过长,TCP划分短一些,过短就积累足够多的字节构成报文段发送出去。
4.2 套接字
- 套接字是一个抽象的概念:socket = (IP地址:端口号),TCP连接:{套接字}:{套接字},同一个IP地址可以有多个不同的TCP连接,同一个端口号也可以出现在多个不同的TCP连接中。
4.3 可靠传输的工作原理
基本原理:当出现差错时让发送方重新传输出错的数据,同时在收方来不及处理数据时,及时告知发送方降低发送速率。
- 停止等待协议(最简单的协议,实际运输层并没有采用):发送完一个分组后停止发送,等待对方的确认,收到确认后再发送下一个分组,如果收不到对方确认,超时重传,而产生超时重传的原因可能是收方的确认丢失了,也可能是发送方发送的分组出错或者丢失,因此对于收方,对于重传的分组,假如是已经收到过的分组,此时需要执行丢弃重复分组,向发送方发送确认的动作。对于可能迟到的确认,发送方执行收下丢弃的处理。这种自动重传的协议我们称之为ARQ(Automatic Repeat request)协议。
- ARQ协议最大的缺点是信道利用率太低,要一直等待来回往返的确认RTT时间,如果往返时间大于分组发送时间Td,那么信道利用率是非常低的。因此未来提高传输效率,采用流水线发送,也就是连续ARQ协议和滑动窗口协议。
- 连续ARQ协议与go-back-N
4.4 TCP报文段首部
有几个比较重要的概念:
- 序号:占4个字节,一个TCP连接中的传输的字节流都要按顺序编号,比如一个报文字节序号为301,携带100个字节数据,那么该报文中第一个字节的序号为301,最后一个字节为400,下一个报文的序号字段值应为401
- 确认号:占4个字节,是期望收到对方下一个报文段的第一个数据字节的序号。比如B正确收到了A发来的501-700的数据,那么B发送给A的确认报文中确认号位701,确认号=N,则表明到序号N-1为止所有数据都正确收到。
- 窗口:窗口值告诉对方从本报文首部确认号算起,接收方目前允许对方发送的数据量,(接收方的缓存是有限的)。B返回给A确认号701,窗口字段为1000,也就是告诉对方,从701开始,我的接收缓存空间还可接收1000个字节数据,你在发送数据时,必须考虑这一点。窗口字段明确指出现在允许对方发送的数据量,窗口值经常在动态变化。
- 选项:最大报文段长度MSS,窗口扩大项,时间戳(可处理**TCP序号超过2^32的情况,防止序号绕回)
5. TCP的可靠传输的实现
以字节为单位的滑动窗口:发送方A的发送窗口,接收方B的接收窗口
- 发送方缓存:发送缓存用于存放准备发送的数据和已经发送但尚未收到确认的数据
- 发送窗口:发送窗口是发送缓存的一部分,已经确认的数据应当从发送缓存中删除,因此发送缓存和发送窗口的后沿是重合的(注意发送程序需要控制写入缓存的速率,太快会导致缓存没有存放数据的空间,因为发送的数据可能还未被确认)
- 接收缓存存放:按序到达但还没有被应用接收的数据和未按序到达的数据
- 接收窗口:如果收到分组出错,就要丢弃,如果接收应用程序来不及接收数据,接收缓存会被填满,接收窗口会被减小为零,如果能够及时处理,接收窗口就可以增大,接收窗口动态调整,并反馈给发送方,以通知发送方调整发送速率。
- 发送窗口两个决定因素:1.B的接收窗口作为参考 2.根据网络拥塞情况适当减小发送窗口数值
- 整个发送过程可以描述为:
- A可以将窗口内的数据都发送出去,在此期间不需要收到B的确认情况,凡是没有得到确认的已发送数据暂时保留,以便超时重传。
- B接收窗口对按序收到的数据的最高序号给出确认,如果B确认收到这些数据,就将接收窗口向前移动,并给A发送确认,A收到确认后,就将发送窗口向前移动。
- 如果A一直发送数据,一直到整个发送窗口内的数据发送完毕,也没有收到B的确认,那么A的发送窗口已满,则需要停止发送,经过一段时间(超时)重传这部分数据,直到收到B的确认,就可以向前移动窗口了。
- 超时重传的时间选择
- 过短,引起不必要的重传,过长,空闲时间增大,降低效率
- 自适应算法,记录报文段往返时间RTT(报文发出到收到确认之间的时间),通过测量RTT,获得一个加权平均往返时间RTTs
新RTTs = (1-α)*旧RTTs + α * 新RTT样本(α通常为0.125)
则超时重传时间RTO为:RTO= RTTs + 4 * RTTd(RTT的偏差加权平均值) - Kam算法:在计算加权平均RTTs的时候,只要报文段重传了,就不采用其往返时间样本。
6. TCP的流量控制
注意理解流量控制和拥塞控制的区别
- 流量控制:flow control,让发送方发送速率不要太快,要让接收方来得及接收,也就是说是一对一,发送方和接收方的协商
- 流量控制的实现:滑动窗口机制,发送方的接收窗口不能超过接收方的接收窗口,接收方在发送ACK时可向发送方发送rwnd字段,告知接收窗口的大小进行流量控制
- 注意死锁的产生:B向A发送了零窗口报文后,过一段时间后B有了空间并向A发送rwnd = n的报文段,但是该报文段丢失了,这个时候A在等待B,B也在等待A重新发送数据,导致了互相等待的死锁局面。解决方法是当TCP连接的一方接到对方的零窗口通知,就启动持续计时器,如果时间到,就发送一个零窗口探测报文段。
- TCP传输效率:控制TCP发送报文段的时机
- Nagle算法:Nagle算法就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。Nagle算法的基本定义是任意时刻,最多只能有一个未被确认的小段。 所谓“小段”,指的是小于MSS尺寸的数据块,所谓“未被确认”,是指一个数据块发送出去后,没有收到对方发送的ACK确认该数据已收到。
(1)如果包长度达到MSS或者发送窗口大小的一半,则允许发送;
(2)如果该包含有FIN,则允许发送;
(3)设置了TCP_NODELAY选项,则允许发送;
(4)未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送;
(5)上述条件都未满足,但发生了超时(一般为200ms),则立即发送。- 糊涂窗口综合征(silly window syndrome)
7. TCP的拥塞控制
7.1 拥塞控制与流量控制的区别
- 拥塞产生的原因:对网络资源的需求大于可用的资源,可能是带宽不够,也可能是交换结点的缓存太小,也可能是发送方发送数据过快,而接受方接受数据过慢
- 拥塞控制:拥塞控制是防止过多的数据注入到网络中,这样使得网络中路由器或者链路不至于过载,拥塞控制是一个全局性控制,涉及到所有主机、所有路由器以及降低网络传输性能有关的因素,相对于流量控制,流量控制是点对点通信量的控制,是一个端到端的问题,抑制发送端发送速率,以便接收端来得及接收。
- 拥塞控制容易与流量控制搞混,实际上某些拥塞控制就是通过向发送端报告网络情况,减缓发送速率来实现拥塞的控制
- 拥塞控制由开环控制和闭环控制两种方法:
- 开环:设计网络时充分考虑有关拥塞情况,力求网络工作时不发送拥塞
- 闭环:检测系统网络以便检测拥塞在何处发生何时发生,然后根据拥塞产生的信息来调整网络运行状态,调整状态的操作如增大网络某些可用资源,或减少用户对某些资源的额需求等,调整过程也是一个动态变化的过程
7.2 TCP拥塞控制方法
TCP拥塞控制算法包括:快开始(Slow-start),拥塞避免(congestion avoidance),快重传(fast retransmit)和快恢复(fast recovery),这四个算法是配合起来使用的,以实现拥塞控制,当然这里的拥塞控制本质上是流量控制
-
判断网络拥塞的依据:出现超时
-
慢开始:当主机开始发送数据时,并不清楚网络的负载情况,如果将大量字节注入网络,有可能引起网络拥塞,那么可以先探测一下,由小到大逐渐增大拥塞窗口数值,也就是逐渐增大发送窗口。初始拥塞窗口cwnd设置不超过2-4个SMSS(sender maximum segement size)
- 慢开始规定,每收到一个对新的报文段的确认后,就可以将拥塞窗口增加最多一个SMSS数值,也就是每次增加量 = min(N,SMSS),N是原先未确认,但是现在刚收到确认的字节数
- 如图所示,每经过一个传输轮次,拥塞窗口cwnd就加倍,(传输轮次是指往返时间RTT,就是将发送窗口中所有数据都发送出去了,并且发送方收到了对该窗口中最后一个字节的确认的这样一个轮次)
- 慢开始的慢在于TCP刚开始发送时是一个试探性发送的状态,其窗口cwnd的增长速率并不慢,是呈指数增长的。
-
拥塞避免:因为慢开始的增长速率很快,cwnd很快就变得很大,如果增长过快就会产生网络拥塞,所以需要一个慢开始门限。在cwnd达到门限之后,采用拥塞避免算法,使得cwnd缓慢线性增长。
- cwnd<ssthresh,使用慢开始算法,cwnd>ssthresh,使用拥塞避免,cwnd = ssthresh,两者皆可
- 拥塞避免每经过一个RTT时间,将cwnd加1,也就是加法增大,线性规律增长;
- 如果当达到某一窗口大小,产生超时,发送方判断为拥塞产生,则**调整门限值ssthresh = cwnd(当前值)/2, cwnd = 1(调整为1,进入慢开始)
-
快重传:目的是当网络没有产生拥塞,但是出现个别报文段丢失,为了避免发送方认为超时进入慢开始状态,应尽快在超时的限制时间内让发送方尽早知道有个别报文段产生了丢失,以尽快进行重传,这样就不会产生超时,不会被默认为存在网络拥塞。
- 快重传算法要求立即确认,要求接受方不使用捎带确认,而是即使收到了失序报文段也要立即发出对已收到报文段的额重复确认。
- 算法规定,只要连续收到3个重复确认,就知道是哪一段对方没有收到,应道立即进行重传
-
快恢复:承接快重传,发送方知道已经丢失了个别报文段,执行快回复算法,调整门限ssthresh = cwnd /2,设置cwnd = ssthresh,并开始执行拥塞避免算法,也有将ssthresh = cwnd/2 +3
-
注意:发送方窗口是由网络拥塞情况和对方的接收窗口共同决定的
发送窗口上限值 = Min -
主动队列管理:AQM(active queue management),路由器内部队列采用先入先出规则,如果队列已满,会丢弃再到达的分组,如果被动的队满丢弃,容易影响很多TCP连接,导致全局同步,全局通信量下降,所以采用主动队列管理,当网络拥塞出现某些征兆的时候,主动丢弃某些分组,随机早期检测就是当队列平均队列长度达到一定值时,按照某种概率丢弃个别分组,这样让拥塞控制只在某些TCP连接上出现。
8. TCP连接建立,数据传输和连接释放
- TCP采用C/S模型,主动发起连接的是客户,等待连接的是服务器
- A和B都各自选择初始序列号 x,y
- SYN = 1 即SYN报文段不能携带数据,但要消耗一个序号
- ACK报文段可以携带数据,如果不携带数据就不消耗序号
- 为什么A最后还要再发送一个ACK?是为了防止已经失效的连接报文请求突然传送到B,因而产生错误
- B结束TCP连接的时间要早于A
- 当A处于FIN-WAIT-2状态时,TCP处于半关闭状态,也就是说这个时候A已经不需要发送数据给B了,但是如果B有数据想要发送,A仍然需要接收
- A接收到B释放连接报文并返回ACK后处于TIME-WAIT状态,还要等待2MSL才可以释放连接
- 实现终止TCP全双工连接的可靠性:假设最后的ACK丢失,服务器会重发FIN,因此客户端需要维护状态信息以允许重发最终的ACK(对于主动断开连接的服务器是同样的道理)保证A发送的最后一个ACK报文段能够到达B
- 保证老的重复分节在网络消失:保证来自先前连接的老的重复分组已经消失,2MSL(maximum segment lifetime 最长分节生命)时间足够让某个方向上的分组丢弃