传输层概述
传输层负责向应用层提供通信服务,在它之下是网络层。传输层和网络层的明显区别在于,网络层负责规定主机之间的通信规则,传输层规定的是进程之间的通信规则(又叫做端到端的通信).传输层存在的意义在于,通信的真正端点并不是主机而是主机中的进程,如下图。

传输层的复用和分用
传输层有一个重要的功能就是复用和分用。
复用
就是所有应用层的进程都可以通过传输层再传送到IP层(网络层)
分用
就是传输层从IP层(网络层)接收到发送给本主机应用的数据后,负责分别交付对应的各应用进程
实现分用的方法就是我们常说的使用服务器端口号,注意这个端口实际上是软件端口,非硬件端口。只要发送方负责把报文传送到接收方某个合适的端口,剩下的交付应用进程的任务就交给TCP、UDP来完成。也就是说,两个计算机中的进程要互相通信,要明确对方的IP地址和端口号Port
传输层有两个主要的协议:TCP和UDP,下面就简单的介绍一下两种协议各自的特点
UDP协议
UDP协议是不面向连接的服务,即传送数据之前不需要先建立连接。是不可靠传输的协议,特点是:
- 不可靠传输,速度快
- 差错检验(但不纠错)
- 首部开销小(8个字节)
- 面向报文的传输
- 可以一对多、多对多传输
UDP首部格式

其中,伪首部仅仅是在传输层构造用于计算校验和的作用,既不向下层传递也不向下层传递
校验和的计算方法
把所有内容:首部+数据 都进行计算


在接收方收到数据时,接收方只需计算所有数据的和,如果16bit全为1,则表示无差错 (为什么全为1,因为发送方的校验和在计算时把和的结果取反码,并且加到了首部中,那么接收方求和就是把和的结果 加上 和的结果的反码 = 1111……(16位)
面向报文
面向报文的传输方式是,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。若报文太长,则到达IP层需要分片,降低效率。若太短,则传输效率会下降(举个例子,1字节的数据,加上20字节的UDP首部,再加上20字节的IP层首部,结果发了41字节的包只完成了1字节有用数据的交付)。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说。
TCP协议
TCP协议是面向连接的服务,特点是:
- 可靠传输,速度较UDP慢一些
- 差错检验
- 按序交付
- 流量控制
- 拥塞控制
- 首部开销大(至少20个字节)
- 面向字节流的方式传输
- 只支持一对一传输
面向字节流
面向字节流传输,应用程序交给TCP的是一次一个数据块(大小不等),TCP把它看成是一连串的无结构的字节流。TCP自行缓冲保存,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去
可靠传输
需要明确的是,TCP的可靠传输是建立在网络层IP协议的不可靠传输之上的,TCP协议要采取适当的手段才能保证传输的可靠性。
这里有一个问题:TCP在传输层的可靠性和链路层保证的可靠性有什么区别,为什么我们还要再次保证可靠性呢?
直接的区别就是:链路层保证的可靠性是保证数据在数据链路上的传输无误,保证正确再向上层递交,传输层的可靠性是保证数据要到达应用层的最后一刻是正确的。 其中有一种可能性就是,到达链路层的数据是正确的,但是往上到网络层出现了错误,所以传输层就负责来纠正网络层的错误。
TCP首部格式

- 确认号:期望收到对方下一个报文的第一个数据字节的序号。即已收到的报文段序号+已收到的报文数据长度 + 1 = 确认号
- 数据偏移:指明报文中的数据部分距离报文首部(从零开始)有多远
- 保留位:暂时不作规定,默认为0
- URG:表示紧急情况,要最优先处理(常用于某些数据的撤销),在接收方窗口大小为0时也可以发送
- ACK:表示确认,只有当ACK=1时确认号字段才有效,规定建立连接之后传送的所有报文都需要把ACK=1
- PSH:表示推送,TCP发送端应该立即创建一个报文段发送,接收方应该尽快交付给应用进程。不应该等多个数据到了才一起递交
- RST:表示复位,在主机崩溃的情况下,释放连接。或者用于拒绝非法报文
- SYN:表示同步,用于请求建立连接或者接受连接
- 窗口:表示接收方告知发送方最大接受的数据量,通常小于接收方的缓存空间
- 紧急指针:指出紧急数据的末尾在报文段中的位置。
- 选项:最长为40字节,可加入报文段的数据字段最大长度MSS(指定TCP向IP层递交数据的最大长度,其大小应该使得传输尽量多的数据同时又使得IP层不需要再次分片)、窗口扩大选项(原本窗口大小为16位2进制,现在最多可以在补充14位,达到30位2进制)、时间戳(用于计算RTT和处理序列号超过2^32绕回0出现原本序号重复的问题)
滑动窗口
滑动窗口是以字节为单位的,发送方和接收方各有一个窗口,接收方通过 TCP 报文段中的窗口字段告诉发送方自己的窗口大小,发送方根据这个值和其它信息设置自己的窗口大小。
发送窗口内的字节都允许被发送,接收窗口内的字节都允许被接收。窗口外的字节不可发送。如果发送窗口某个字节已经发送并且收到了确认,那么就将发送窗口向右滑动到第一个处于未确认状态的字节;接收窗口的滑动类似,接收窗口左部字节已经发送确认并交付应用程序,就向右滑动接收窗口。(注意:如果是确认接收但未交付应用程序的字节,还会留在窗口内)

窗口和缓存之间的关系
缓存通常都要比窗口设置的值要大一些,如下图
发送缓存存放:
- 发送应用程序传送给下层TCP准备发送的程序(即未进入发送窗口的数据)
- TCP已发送但未确认的数据
接收缓存存放:
- 按序到达的、但尚未被应用程序接收的数据
- 接受应用程序
所以缓存的大小也会影响到滑动窗口的工作。
超时重传时间的选择
(待补充)
流量控制
是滑动窗口协议的具体应用。通过接收方返回的 ACK 中所包含自己接收窗口的大小来控制发送方的数据发送。
如何控制TCP发送报文的时机?
捎带确认
当用户(应用层)只发送1个字节时,应该尽量使用捎带确认的方法
Nagle算法:
纳格算法的工作方式是合并一定数量的输出数据后一次提交。特别的是,只要有已提交的数据包尚未确认,发送者会持续累积直到一定数量的数据才提交。并且任意时刻,最多只能有一个未被确认的包
if有新资料要传送
if窗口大小>= MSS and可传送的资料>= MSS
立刻传送
else
if管线中有尚未确认的资料
在下一个确认(ACK)封包收到前,将资料排进缓冲区伫列
else
立即传送
延迟确认
和Nagle算法思想是一致的
接收方收到数据包以后如果暂时没有数据要发给对端,它可以等一段时再确认。如果这段时间刚好有数据要传给对端,ACK就随着数据传输,不需要单独发送一次ACK。如果超过时间还没有数据要发送,也发送ACK,避免发送方以为丢包
糊涂窗口综合征
糊涂窗口综合症的成因
- 当客户端每次只能生成1个字节(传输效率低)
- 当服务器一次只能消耗1个字节(传输效率低)
解决方案
- 如果糊涂窗口综合症是由发送方产生,则Nagle算法发挥作用: 要求发送方累积到最大大小段(MSS)或者收到接收方的一个确认就发送新数据。
- 如果糊涂窗口综合症由接收方产生,则Clark算法发挥作用:关闭窗口,直到缓存空间已能放入具有最大长度的报文段,或者缓存空间的一半已经空了
拥塞控制
(待补充)
参考: 1.计算机网络(第七版)-谢希仁