计算机网络_运输层
在IP层看来,通信的两端是两个主机,IP数据报的首部明确的标志了这两个主机的IP地址。但是两个主机之间的通信这种说法还不够清楚,这是因为真正进行通信的实体是在主机中的 进程 ,是两个进程之间在交换数据。从而引出了运输层,从运输层的角度看来, 通信的真正端点并不是主机而是主机中的进程 (端到端的通信)。
在一个主机中经常有多个应用进程同时分别和另一个主机的多个应用进程通信。这就表明了运输层有一个很重要的功能, 复用和分用 ,应用层不同进程的报文通过不同的端口向下交到运输层,再往下就共用网络层提供的服务。
“运输层提供应用进程间的逻辑通信”。“逻辑通信”的意思是:运输层之间的通信好像是沿水平方向传送数据。但事实上这两个运输层之间并没有一条水平方向的物理连接。
TCP/IP 的运输层有两个不同的协议:
由此可见两个计算机中的进程要相互通信,不仅要知道对方的IP地址,还要知道对方的端口号。
如果接收方UDP发现收到的报文中的目的端口号不正确(即不存在对应于该端口的号的应用进程),就丢弃该报文,并由网际控制报文协议ICMP发送 端口不可达 差错报文给发送方。
在计算检验和时,临时把 “伪首部” 和 UDP 用户数据报连接在一起得到一个临时的数据报,它不向下传递也不向上递交。 伪首部仅仅是为了计算检验和 。
UDP计算检验和的方法和IP数据报首部检验和方法相类似。但不同的是,IP数据报的检验和 只检验IP数据报的首部 ,但UDP的检验和是 把首部和数据部分一起检验
计算UDP检验和的例子:
在发送方,先把全0放入检验和字段,再把伪首部以及UDP用户数据报看成是许多16位的字串接起来。若UDP用户报的数据部分不是偶数个字节,则要填入一个全零字节(先不发送)。然后按照 二进制反码 计算出这些16位字的和。将此和的二进制反码写入 检验和字段 后,就发送这样的UDP数据报。在接收方,把收到的UDP数据报连通伪首部(以及可能填充全零字节)一起,按二进制反码求这些16位字的和。当无差错时其结果应为全1(原本的检验和为0,封装成数据报后再次相加的时候就多个检验和反码相加,所以无差错时结果为1)。
每一条TCP连接唯一地被通信两端的两个端点(即两个套接字)所确定,即:
TCP发送的报文段是交给IP层传输的。但IP层只提供尽最大努力服务,也就是说,TCP下面的网络所提供的是不可靠传输,因此,TCP必须采用适当的措施才能使得两个运输层之间的通信变得可靠。
在这样的理想传输条件下,不需要采取任何措施就能够实现可靠传输。然而实际的网络都不具备以上两个理想的条件。但我们可以使用一些可靠传输协议,当出现差错时让发送方重传出现差错的数据,同时在接收方来不及处理收到的数据时,及时告诉发送方适当的降低发送数据的速度,这样一来,本来是不可靠的传输信道就能够实现可靠传输。
停止等待协议的优点是简单,但缺点是 信道利用率 太低。
假定AB之间有一条直通的信道来传送分组
这里的TD是A发送分组所需要的时间(显然TD = 分组长度 / 数据速率)再假定TA是B发送确认分组所需要的时间(A和B处理分组的时间都忽略不计)那么A在经过TD+RTT+TA时间后才能发送下一个分组,这里的RTT是往返时间,因为只有TD是采用来传输有用的数据(这个数据包括了分组首部,如果可以知道传输更精确的数据的时间,可以计算的更精确),所有信道利用率为
为了提高传输效率,发送方可以不使用低效率的停止等待协议,而是采用 流水线传输 :就是发送方可以 连续的发送多个分组 ,不必每发完一个分组就停下来等待对方的确认。这样可使信道上一直有数据不间断地在传送。显然这种传输方式可以获得很高的信道利用率
当时使用流水线传输时,就要使用下面介绍的 连续ARQ协议 和 滑动窗口协议
滑动窗口协议比较复杂,是TCP协议的精髓所在,在这里先给出ARQ协议最基本的概念,但不涉及到许多细节问题。
位于发送窗口的分组都可以连续的发送出去,而不需要等待对方的确认,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。
详细可以见P201
TCP虽然是面向字节流的,但是TCP传送的数据单元却是报文段(可以看上述TCP面向流的概念),而且TCP的 全部功能都体现在它的首部中各个字段 。
详解请见P206,注意图中的后沿,前沿
从下图可以看出来,要描述一个发送窗口的状态需要三个指针:P1,P2,P3
有很多信息见P208,这里不赘述
发送方的应用进程把字节流写入TCP的发送缓存,接收方的应用进程从TCP的接收缓存中读取字节流。下面进一步讨论前面讲的 窗口和缓存 的关系
发送缓存
发送窗口通常只是发送缓存的一部分,已被确认的数据应当从发送缓存中删除,因此 发送缓存和发送窗口的后沿是重合 的。发送应用程序最后写入发送缓存的字节减去最后被确认的字节,就是还保留在发送缓存中被写入的字节。发送应用程序必须控制写入缓存的速率,不能太快 ,否则发送缓存就会没有存放数据的空间。
如果收到的分组被检测出有差错,则要丢弃。如果接收应用程序来不及读取收到的数据,接收缓存最终就会被填满,使接收窗口减少到零。反之,如果接收应用程序能够及时从接收缓存中读取收到的数据,接收窗口就可以增大,但最大不能超过接收缓存的大小。
TCP才用了一种自适应算法,它记录一个报文段发出的时间,以及收到相应的确认的时间。这两个时间之差就是报文段的往返时间RTT。
TCP 保留了 RTT 的一个 加权平均往返时间 RTTs (这又称为平滑(smooth)的往返时间,因为是加权平均,所以是平滑的)。
第一次测量到 RTT 样本时, RTTS 值就取为所测量到的 RTT 样本值 。以后每测量到一个新的 RTT 样本,就按下式重新计算一次 RTTS:
显然,RTO 应略大于上面得出的加权平均往返时间 RTTs
RFC 2988 建议使用下式计算 RTO:
RTTD 是 RTT 的 偏差的 加权平均值,他与RTTs和新的RTT样本之差有关。
RFC 2988 建议这样计算 RTTD。第一次测量时,RTTD 值取为测量到的 RTT 样本值的一半。在以后的测量中,则使用下式计算加权平均的 RTTD:
β是个小于 1 的系数,其推荐值是 1/4,即 0.25。
为了解决上面那个问题,Karn提出了一个算法
在计算平均往返时间 RTT 时,只要**报文段重传了,就不采用其往返时间样本。这样得出的加权平均平均往返时间 RTTS 和超时重传时间 RTO 就较准确。 **
但是,这又有了新的问题、设想出现这样的情况:报文段的时延突然增大了很多。因此在原来得出的重传时间内,不会收到确认报文段。于是就重传报文段。但根据Karn算法,不考虑重传的报文段的往返时间样本。这样,超时重传时间就无法更新。
报文段每重传一次,就把 RTO 增大一些:
系数 γ 的典型值是 2 。
当不再发生报文段的重传时,才根据报文段的往返时延更新平均往返时延 RTT 和超时重传时间 RTO 的数值。
实践证明,这种策略较为合理。
接收方收到了和前面的字节流 不连续 *的两个字节块(只是未按序号,它是无差错的)
如果这些字节的序号都在接收窗口之内,那么接收方就先收下这些数据,但要把这些信息准确地告诉发送方,使发送方不要再重复发送这些已收到的数据。
和前后字节不连续的每一个字节块都有两个边界:左边界和右边界。图中用四个指针标记这些边界。第一个字节块的左边界 L1 = 1501,但右边界 R1 = 3001。左边界指出字节块的第一个字节的序号,但右边界减 1 才是字节块中的最后一个序号。第二个字节块的左边界 L2 = 3501,而右边界 R2 = 4501。
详见P211
一般说来,我们总是希望数据传输得更快一些。但如果发送方把数据发送得过快,
接收方就可能来不及接收,这就会造成数据的丢失。
流量控制(flow control)就是让发送方的发送速率不要太快,既要让接收方来得及接收,也不要使网络发生拥塞 。
利用 滑动窗口机制 可以很方便地在 TCP 连接上实现流量控制。
A 向 B 发送数据。在连接建立时,�B 告诉 A:“我的接收窗口 rwnd = 400(字节)”。 看下TCP首部窗口字段的用处
接收方的主机B一共进行了3次流量控制(蓝线)
考虑一种情况,B向A发送了零窗口的报文段后不久,B的接收缓存又有了一些存储空间。于是B向A发送了rwnd = 400的报文段,然而这个报文段在传输过程中丢失了。A一直等收到B发送非零窗口的通知,B也一直等A发送数据来,就形成了 死锁 。下面的 持续计时器 就是为了打破死锁僵局的
应用进程把数据传送到TCP发送缓存后,剩下的发送任务就由TCP来控制了。可以用不同的机制来控制 TCP 报文段的发送时机:
至于如何控制发送的 时机 详见P213
在某段时间,若对网络中某资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏——产生 拥塞(congestion)
出现资源拥塞的条件: 对资源需求的 总和 > 可用资源
若网络中有许多资源同时产生拥塞,网络的性能就要明显变坏,整个网络的吞吐量将随输入负荷的增大而下降。
解决拥塞的要点是 平衡 ,要让整个系统的性能想匹配(P214)。
横坐标为 提供的负载 ,代表单位时间内输入给网络的分组的数目(也叫作输入负载或网络负载),纵坐标是 吞吐量 ,代表单位时间内从网络输出的分组数目。
由于缺少缓存空间而被丢弃的分组的百分数,平均队列长度,超时重传的分组数,平均分组时延,分组时延的标准差等,这些指标的上升都标志着拥塞的增长。
方便起见,我们用 报文段的个数 作为窗口大小的单位
慢开始门限 ssthresh 的用法如下:
拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢地增大,即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1,而不是加倍,使拥塞窗口 cwnd 按线性规律缓慢增长 ,比慢开始算法的拥塞窗口增长速率缓慢很多。
网络出现拥塞时
当 TCP 连接进行初始化时,将拥塞窗口置为 1。图中的窗口单位不使用字节而使用 报文段 。
慢开始门限的初始值设置为 16 个报文段,即 ssthresh = 16。
发送端的发送窗口不能超过拥塞窗口 cwnd 和接收端窗口 rwnd 中的最小值。我们假定接收端窗口足够大,因此现在发送窗口的数值等于拥塞窗口的数值。
下面的执行步骤就是按照折现上的点的顺序