本章纲要
- 传输层提供的服务
-
- 传输层的功能
-
- 传输层寻址和端口
-
- 无连接服务和面向连接服务
- UDP协议
-
- UDP 数据报
-
- UDP 校验
- TCP协议
-
- TCP 段
-
- TCP 连接管理
-
- TCP 可靠传输
-
- TCP流量控制和拥塞控制
我们关键需要掌握传输层的功能,工作方式和原理,需要重点掌握UDP,TCP协议(包括报文分析,首部格式,可靠传输,流量控制,拥塞控制,连接管理)。
1. 传输层提供的服务
1.1 传输层的功能
传输层是一个介于面向通信和面向用户功能的中间人。
- 传输层为应用进程提供逻辑通信,网络层提供的是主机的逻辑通信
- 在网络层进行的差错校验是对IP数据报的首部进行校验,传输层还要对首部+数据进行同时的校验
- 传输层提供了两种传输协议:无连接UDP和有连接TCP。
- 和网络层不同,网络层要不只能提供有连接的虚电路,要不只能提供无连接的数据报,不可能在网络层同时提供两种方式的
- 传输层只关注两个传输层的实体之间有一条端对端的信道,不再关注网络的拓扑了
1.2 端口和寻址
端口:端口是方便知道应用进程的对应标识。TSAP 我们叫做 传输层的服务访问点
数据链路层的SAP 是MAC地址,网络层的SAP 是IP地址,传输层的SAP是端口
应用进程用到了端口号来标识应用进程,端口号长度是16Bit,也就说我们最多能标识65536( 2 16 2^{16} 216)个端口。
我们常用的一些服务会使用熟知服务口:
应用程序 | FTP | Telnet | SMTP | DNS | TFTP | HTTP | SNMP |
---|---|---|---|---|---|---|---|
端口号 | 21 | 23 | 25 | 53 | 69 | 80 | 161 |
- 熟知服务端口指派:0-1023
- 等级服务端口范围:1024 - 49151
- 客户端口范围:49152 - 65535
套接字 = [主机IP地址,端口号]
1.3 无连接服务和有连接服务
当采用TCP的时候,传输层对上提供的是一条可靠的全双工信道
采用UDP的是时候,传输层对上提供的是一条不可靠的信道
TCP:应用在FTP,HTTP,Telnet
UDP:应用在TFTP(小文件传送协议),DNS,SNMP和RTP(实时协议)
IP数据报和UDP数据报的区别:IP数据报在网络层需要进行路由的存储和转发,但是UDP数据报是端对端的,对路由的存储和转发不可见
2. UDP 协议
2.1 UDP数据报
如果我们的程序选择了UDP协议的话, 我们很大程度上需要直接和IP打交道
- UDP数据报在IP数据报上增加了两个基本的服务:一个是复用和分用,一个是差错检测
- UDP的优点的无需建立连接,分组开销小,TCP报文的首部是20B,UDP首部只需要8B的开销。
- UDP没有拥塞控制,他能容忍一些数据的丢失
- 适合一次性传输较少量的数据,保持实时性,视频会议等
- 尽最大努力交付,UDP是面向报文的,UDP的报文是不可分割的,UDP的接收方受到了IP数据报之后拆掉UDP用户数据报就直接交给应用上层了。UDP数据报是最小的单位
UDP数据报首部:
UDP数据报保活两个部分:UDP首部和使用户数据,整个UDP数据报首部8B,四个字段,每个字段占2B(16位)
- 源端口:
- 目的端口:
- 长度:UDP数据报的长度
- 校验和:用来校验整个UDP数据报是否有错,有错就丢掉
伪首部并不传送和递交,仅仅是为了计算校验和
3. TCP 协议
TCP/IP是一个用来解决可靠,有序,无丢失,不重复的问题。
- 面向连接的,每一条TCP连接只能有两个端点,支持全双工,接收和发送双发都有缓存
- TCP 是面向字节的
3.1 TCP 报文段
TCP报文也是分为首部和数据两部分,结构如下:
首部长度20B
- 源端口、目的端口:各占2B
- 序号:占4B,保存报文数据第一个字节的序号
- 确认号:占4B,保存报文数据最后字节序号+1。他的意思是前面N-1序号之前的数据都收到了
- 数据偏移:首部长度。单位是4B
- 保留字:为以后需要使用,目前为0
- 窗口:占2B,告知接收方发送方的窗口大小
- 校验和:占2B,计算校验和的时候需要用到伪首部
- 紧急指针:紧急数据(放在报文的最前面)占了多少字节
- 选项:保存数据字段的最大长度
- 填充:为了使得首部的长度是4B的整数倍
- ACK位(确认位):ACK=1确认号才有效,ACK=0确认号无效
- PSH位(推送位):PSH=1的时候接收的时候需要马上交付,不能等缓冲区满了再交付
- RST位(重置位):RST=1标识当前的连接出现了严重差错。
- SYN位(同步位):SYN=1标识这是一个连接请求或者连接接收报文(用来建立连接)
- FIN位(终止位):FIN = 1 标识已经发送完了,要求释放连接
3.2 TCP连接管理
- TCP连接的确认:建立连接,数据传送,连接释放
- 主动发起连接叫做客户机,等待被连接叫做服务机
- TCP建立连接需要三次握手:客户机先发送一个连接请求报文,seq 标识起始的字节序号。
连接的释放我们叫做四次握手
我们如果用逻辑符号表示一下:
ack表示确认号,大写的ACK表示确认位
连接建立:
【1[CtS]】
S
Y
N
=
1
,
s
e
q
=
x
SYN=1,seq=x
SYN=1,seq=x
【2[StC]】
S
Y
N
=
1
,
A
C
K
=
1
,
s
e
q
=
y
,
a
c
k
=
x
+
1
SYN=1,ACK=1,seq=y,ack=x+1
SYN=1,ACK=1,seq=y,ack=x+1
【3[CtS]】
A
C
K
=
1
,
s
e
q
=
x
+
1
,
a
c
k
=
y
+
1
ACK=1,seq=x+1,ack=y+1
ACK=1,seq=x+1,ack=y+1
连接释放:
【1[CtS]】
F
I
N
=
1
,
s
e
q
=
u
FIN=1,seq=u
FIN=1,seq=u
【2[StC]】
A
C
K
=
1
,
s
e
q
=
v
,
a
c
k
=
u
+
1
ACK=1,seq=v,ack=u+1
ACK=1,seq=v,ack=u+1
【3[StC]】
F
I
N
=
1
,
A
C
K
=
1
,
s
e
q
=
w
,
a
c
k
=
u
+
1
FIN=1,ACK=1,seq=w,ack=u+1
FIN=1,ACK=1,seq=w,ack=u+1
【4[CtS]】
A
C
K
=
1
,
s
e
q
=
u
+
1
,
a
c
k
=
w
+
1
ACK=1,seq=u+1,ack=w+1
ACK=1,seq=u+1,ack=w+1
3.3 TCP 可靠传输的实现
我们知道在IP层的传输可能是不可靠的,我们在TCP实现可靠的方法就是增加校验和重传的机制来保证可靠。
序号机制:
我们给每一个的字节进行编号,一句是我们的发送缓冲区有10个字节,那么我们从0开始编号,假如对面收到了数据之后则会发送ACK确认
什么时候出现重传?
超时和冗余ACK:
- 超时:发送端发送了一个TCP报文之后没有在指定时间受到报文,那么就会重传
- 冗余ACK:比如发送端发送了12345序号的字节,然后2在链路层丢失了,那么接收端因为在收到1之后,发现3不是他的期望的,因此,连续三次发送的ACK都是对1的确认,着三个多出来的ACK我们叫做冗余ACK。这个时候发送端收到了3个冗余ACK之后就会推测2序号丢失了,就会重发2。这种叫做快速重传技术
3.4 TCP 进行流量控制
所谓的流量控制就是发送方为了协调接收方缓冲区溢出的可能性而进行的操作。
TCP会提供一种滑动窗口机制,在通信当中接收方会根据自己接收的缓存的大小动态调整发送方的发送窗口大小。
我们利用TCP报文里面首部的字段来限制发送方的报文注入速率。
- 接收窗口:rwnd
- 拥塞窗口:cwnd
发送窗口的大小由接收窗口和拥塞窗口的最小值决定
我们可以看一个TCP进行流量控制的例子:
我们可以发现,发送端的发送控制权实际上掌握在接收方的手上的。
发送端的窗口大小也是由接收方进行调节的。
3.5 TCP 拥塞控制
流量控制和拥塞控制的区别在于:流量控制是防止发送端和接收端不协调而做的控制,拥塞控制是防止在中途的路由器和交换主机数据拥塞的情况发生。
流量控制是解决是端的问题,拥塞控制解决的是路上的问题。
例子:假如我们的某个链路的传输速率是10Gb/s,我们的一台主机用1Gb/s的速率发文件,那接收端的PC不一定能来得及接收,这个时候就需要流量控制。但现在有100万台主机同时以1Mb/s的速率发文件,这个时候我们就要考虑这个网络负载是否超过了能承受的范围了。
拥塞窗口实际上维护就是了全局的网络拥塞情况。
下面讲解一下怎样进行拥塞控制:
慢开始算法:在TCP刚刚连接好,开始发送TCP报文段的时候先令cwnd = 1(这个我们放在首部的选项字段MSS里面),每收到一个新的报文段的确认之后cwnd+1。
假如A向B发送数据,假如A的拥塞窗口是2的时候,一次可以发送两个TCP的报文段,经过一个传输轮次之后,A收到B对刚才两个报文的确认就会把拥塞窗口调到4,那么下一次发送的时候就能发送4个报文段。
当我们的慢开始算法达到一定的阈值之后,(因为每经过一个传输轮次拥塞窗口就会加倍),我们就开始改用拥塞避免算法。
慢开始算法会使得cwnd的大小是按照指数型的增加的。
拥塞避免算法:每经过一个RTT的话,cwnd就加1,就是无论确认多少ACK都+1,保证这个cwnd是按照线性增长。
如果出现一次超时,就使得变成原来的一半
总的来说就是:加法增加,乘法减少。
- 当cwnd<threshold:使用慢开始算法
- 当cwnd>threshold:转成使用拥塞避免算法
一般来说,我们更加倾向于(更加频繁)使用拥塞避免算法,因为指数的增加导致意外的出现更加频繁。
除了慢开始+拥塞避免这样的策略之外,我们还要其他的改进方案吗?
有的,快重传和快恢复就是对拥塞避免算法的改进。
快重传算法:就是之前说过的对于冗余ACK的处理。
快恢复算法:当我们的发送端收到了三个冗余的ACK之后,就执行乘法减少的算法。