目录
运输层协议概述
进程之间的通信
运输层向它上面的应用层提供通信服务,它属于面向通信部分的最高层,也是用户功能中的最低层
因此严格地讲,两台主机进行通信就是两台主机中的应用进程互相通信
IP协议 虽然能把分组送到目的主机,但是这个分组还停留在主机的网络层 而没有交付主机中的应用进程
通信的两端应当是两个主机中的应用进程
网络层 为主机 之间的通信提供服务,运输层 在网络层 的基础上,为应用进程之间的通信提供服务
运输层的两个主要协议
TCP/IP运输层两个主要协议:
- 用户数据报协议UDP
- 传输控制协议TCP
两个运输实体在通信时传送的数据单位 叫作"运输协议数据单元TPDU"
在TCP/IP体系 中,根据所使用的协议是TCP 还是UDP ,分别称之为"TCP报文段"或"UDP报文段"
运输层的端口
应用程序要通过运输层发送到互联网,必须要经过端口,每一个端口都有一个端口号来标志
TCP/IP运输层 用一个16位端口号来标志一个端口(端口号只具有本地意义)
运输层的端口号分为下面的两大类:
- 服务器端使用端口号 :
- 全球通用端口号(熟知端口号):数值为0~1023
- 登记端口号:数值为1024~49151,这类端口号是为没有熟知端口号的应用程序使用的
- 客户端使用端口号(用户端口号):数值为49152~65535,这类端口号仅在客户进程运行时才动态选择,因此又叫作短暂端口号
用户数据报协议UDP
UDP概述
用户数据报协议UDP 只在IP的数据报服务 之上增加了很少一点的功能,这就是"复用 "和"分组 "的功能以及"差错检测 "的功能,UDP的主要特点是:
- UDP是无连接的,即发送数据之前不需要建立连接,减少了开销和发送数据之前的时延
- UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表
- UDP是面向报文的 ,发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层
- UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低
- UDP支持一对一 、一对多 、多对一 、多对多的交互通信
- UDP首部开销小,只有8个字节
UDP首部格式
用户数据报UDP 有两个字段:"数据字段 "和"首部字段"
首部字段 由以下四个字段组成,每个字段长度都是2字节:
- 源端口:源端口号,在需要对方回信时选用,不需要时可用全0
- 目的端口:目的端口号
- 长度:UDP用数据报长度
- 检验和:检测UDP用户数据报在传输中是否有错
在计算检验和时,在UDP用户数据报之前增加12个字节的伪首部,伪首部只在计算检验和时,临时添加在UDP用户数据报前面,得到一个临时的UDP用户数据报
伪首部 既不向下传送 也不向上递交 ,仅仅是为了计算检验和
传输控制协议TCP概述
TCP最主要的特点
- TCP是面向连接的运输层协议:应用程序使用TCP协议之前,必须先建立TCP连接。在数据传送完毕后,必须释放已经建立的TCP连接
- 每一条TCP连接只能有两个端点:每一条TCP连接只能点对点的
- TCP提供可靠交付的服务:通过TCP连接传送的数据,无差错、不丢失、不重复并且按序到达
- TCP提供全双工通信:TCP允许通信双方的引用进程在任何时候都能发送数据
- 面向字节流:TCP中的"流"指的是"流入到进程或从进程流出的字节序列"。TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。TCP并不知道所传送字节流的含义
TCP的连接
TCP 把连接作为最基本的抽象
TCP 连接的端点叫"套接字 "或"插口"
端口号 拼接到IP地址 即构成了套接字 (scoket ),即在点分十进制的IP地址 后面写上端口号,就构成了套接字
每一条TCP连接 唯一地被通信两端发的两个端点所确定:
同一名词socket可以表示多种不同的意思:
- 允许应用程序访问连网协议的应用编程接口API
- scoketAPI中使用的一个函数名
- 调用socket函数时,其返回值称为socket描述符
- 调用socket函数的端点
可靠传输的工作原理
停止等待协议
全双工通信 的双方既是发送方 也是接收方
停止等待协议 :"发送方每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组"
无差错情况
如果没有出现差错时,停止等待协议传输过程如下图所示:
出现差错
如果分组在传输过程中出现差错,那么会丢弃差错分组 ,其它什么也不做 (不通知发送方有差错分组)
如果发送方超过一段时间仍然没有收到确认,就认为刚才发送的分组丢失了,因而重传前面发送过的分组,这就叫作"超时重传"
实现"超时重传",就要在每发送完一个分组时设置一个"超时计时器",如果收到该分组的确认,那么就撤销该"超时计时器"
注意:
- A在发送完一个分组后,必须暂时保留已发送的分组的副本(在发生超时重传时使用),只有在收到相应的确认后才能清楚暂时保留的分组副本
- 分组和确认分组都必须进行编号:这样才能明确是哪一个发送出去的分组收到了确认
- 超时计时器设置的重传时间应当比数据在分组传输的平均往返时间更长一些
确认丢失和确认迟到
如果B所发送的确认丢失,那么A会在超时重传器过期后,重新发送分组,这时B再次收到同一个分组 ,它会做出下面两个动作:
- 丢弃这个重复的分组M1,不想上层重复交付
- 向A发送确认。
如果传输过程中没有出现差错,但B对分组的确认迟到了。A在超时重传器过期后,会发送重复分组。
此时B会接收到重复分组,B会丢弃所有重复的分组,并重新发送确认分组
而A在一段时间后收到了重复的确认分组,A会将它们全部丢弃,之后什么也不做
信道利用率
停止等待协议的优点是简单,但缺点是信道利用率太低
停止等待协议的计算方法如下:
- A发送分组需要的时间是TD:TD等于分组长度除以数据率
- B发送确认分组需要的时间是TA
- RTT是分组往返时间
当往返时间RTT 远大于分组发送时间TD 时,信道的利用率就会非常低,为了提高运输效率,我们可以使用流水线传输 (连续ARQ协议和滑动窗口协议)
连续ARQ协议
下图是一个发送方维持的"发送窗口 ",它的意思是:"位于发送窗口内的五个分组都可以连续发送出去,而不需要等待对方的确认"
- "向前 "是指"向着时间增大的方向"
- "向后 "是指"向着时间减少的方向"
- 分组发送 是按照分组序号"从小到大"发送的
连续ARQ协议 规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置
接收方一般都是采用"累计确认"的方式,接收方不必对收到的每个分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认(表示到这个分组为止的所有分组都已正确收到了)
TCP报文段的首部格式
TCP 虽然是面向字节流的,但TCP 传送的数据单元 却是"报文段"
一个TCP 报文段分为"首部 "和"数据"两部分
TCP 报文段首部的20个字节 是固定的 ,后面有4n 字节是根据需要而增加的选项(n是整数 ),因此TCP 首部的最小长度是20字节
首部固定部分各字段意义如下:
- 源端口和目的端口:各占2个字节,分别写入源端口号和目的端口号
- 序号:占4个字节,序号范围是[0,2^32 - 1],公共2 ^ 32个序号,序号增加到2 ^ 32 - 1后,下一个序号就又回到0(mod运算)。TCP连接中传送的字节流中的每一个字节都按顺序编号。
- 确认号 :占4个字节,是"期望收到对方下一个报文段的第一个数据字节的序号 ",例如B收到一个报文段,序号字段值是501,数据长度是200字节,这表示B正确收到了A发送到序号700为止的数据,因此,B期望收到A的下一个数据序号是701,于是B再发送给A的确认报文段中把确认号置为701
- 数据偏移:占4位,表示TCP报文段的首部长度
- 保留:占6位,保留为今后使用,但目前应置为0
- 下面是6个控制位,用来说明本报文段的性质:
- 紧急URG:当URG = 1时,表示紧急指针字段有效。他告诉系统此报文段中有紧急数据,应尽快传送
- 确认ACK:仅当ACK = 1时确认号字段才有效。TCP在连接建立后所有传送的报文段都必须把ACK置为1
- 推送PSH:接收方立即发送响应,不应该将响应送入缓存队列
- 复位RST:当RST = 1是,表明TCP连接中出现严重差错,必须释放连接
- 同步SYN:在连接建立时用来同步序号,当SYN = 1而ACK = 0时,表明这是一个连接请求字段,对方若同意建立连接,则在响应报文段中使SYN = 1和ACK = 1
- 终止FIN:当FIN = 1时,表明释放该运输连接
- 窗口:占2字节,范围在[0,2 ^ 16 - 1],表明接收方目前允许对方发送的数据量
- 检验和:占2字节
- 紧急指针:占2字节,当URG = 1时,它指出本报文段中的紧急数据的字节数
- 选项:长度可变,最长可达40字节,最小为0
TCP可靠传输的实现
以字节为单位的滑动窗口
TCP 的滑动窗口 是以字节为单位的
现假定A收到了B发来的确认报文段,其中窗口是20字节 ,而确认号是31,根据这两个数据,A就构造出自己的发送窗口,如下图所示:
发送窗口 表示:在没有收到B的确认的情况下,A可以连续把窗口内的数据都发送出去。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用
发送窗口前沿不动的两种情况:
- 没有收到新的确认,对方通知的窗口大小也不变
- 收到了新的确认,但对方通知的窗口缩小了,使得发送窗口前沿正好不动
发送窗口前沿向后收缩的情况:
- 对方通知的窗口缩小,但TCP标准强烈不赞成这样做
描述一个发送窗口的状态需要三个指针 :P1、P2、P3
- P1之前的数据是已发送并收到确认的部分
- P3(包括P3)之后的数据是不允许发送的部分
- P3 - P1 = A的发送窗口 = 20
- P2 - P1 = 已发送但尚未收到确认的字节数
- P3 - P2 = 允许发送但当前尚未发送的字节数(又称为"可用窗口 "或"有效窗口")
下面是发送方维持的发送缓存 和发送窗口 ,以及接收方维持的接收缓存 和接收窗口
发送缓存用来存放:
- 发送应用程序传送给发送方TCP准备发送的数据
- TCP已发送出但尚未收到确认的数据
接收缓存用来存放:
- 按序到达的、但尚未被接收应用程序读取的数据
- 未按序到达的数据
超时重传时间的选择
TCP 使用"自适应算法 "来规定超时重传时间 ,它记录一个报文段发出的时间,以及收到相应的确认的时间。这两个时间之差就是报文段的往返时间RTT
TCP 保留了RTT的一个加权平均往返时间RTT (又称为平滑的往返时间)
RTT计算方法:
超时重传时间RTO:
RTTD是RTT的偏差的加权平均值:
在计算加权平均RTTS时,只要报文段重传了,就不采用其往返时间样本
选择确认SACK
选择确认SACK 用来处理:"收到的报文段无差错,只是未按照规定顺序到达,中间还缺少些序号的数据"
TCP的流量控制
利用滑动窗口实现流量控制
流量控制 :"让发送方的发送速率不要太快,要让接收方来得及接收"
发送方的发送窗口不能超过接收方给出的接收窗口的数值
TCP 的窗口单位是字节
TCP传输效率
TCP 传输广泛使用Nagle算法:
若发送应用进程把要发送的数据集逐个字节地送到TCP的发送缓存,则发送方就把第一个数据字节先发送过去,把后面到达的数据字节都缓存起来。
当发送方收到对第一个数据字符的确认后,再把发送缓存中的所有数据组装成一个报文段发送出去,同时继续对随后到达数据进行缓存
只有在收到对前一个报文段的确认后才继续发送下一个报文段,同时继续对随后到达的数据进行缓存
TCP的拥塞控制
拥塞控制的一般原理
在某段时间内,若对网络中某一资源的需求超过了该资源所能提供的可用部分 ,网络的性能就要变坏,这就叫作"拥塞"
拥塞控制 :"防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不至于过载"
流量控制 :"点对点通信量的控制,是个端到端的问题"
TCP的拥塞控制方法
TCP 进行拥塞控制 的算法有四种:"慢开始 "、"拥塞避免 "、"快重传 "、"快恢复"
慢开始和拥塞避免
发送方 维持一个拥塞窗口cwnd的状态变量
拥塞窗口的大小取决于网络的拥塞程度,并且是动态变化着的
发送方控制拥塞窗口的原则是:
只要网络没有出现拥塞,拥塞窗口就可以再增大一些。
只要网络出现拥塞或有可能出现拥塞,就把窗口减小一些
发送方在超时重传计时器启动时,就判断网络出现了拥塞
慢开始算法思路:
当主机在已建立的TCP连接上开始发送数据时,并不清楚网络当前的负荷情况。因此由小到大的逐渐增大注入到网络中的数据字节 (由小到大逐渐增大拥塞窗口数值)
- 若最大报文段SMSS > 2190字节:则设置初始拥塞窗口cwn = 2 * SMSS
- 若SMSS > 1095 && SMSS <= 2190:cwnd = 3 * SMSS
- 若SMSS <= 1095:cwnd = 4 * SMSS
慢开始规定,在没收到一个对新的报文段的确认后,可以把拥塞窗口增加到最多一个SMSS的数值
TCP的运输连接管理
TCP是面向连接的协议。
运输连接 时用来传送TCP报文的。
运输连接 有三个阶段:"连接建立 "、"数据传送 "、"连接释放"
TCP的连接建立【重要】
TCP建立连接的 过程叫作握手 ,握手需要在客户和服务之间交换三个TCP报文段:
- 第一次请求报文段 :SYN = 1,同时选择一个初始序号seq = x,此时TCP客户进程进入SYN-SENT(同步已发送)状态
- B收到连接请求报文后 ,如果同意建立连接,则向A发送确认。在确认报文段中应把SYN和ACK都置1,确认号ack = x + 1,同时为自己选择一个初始序号seq = y,此时进入SYN-RCVD(同步收到)状态
- TCP客户进程收到B的确认后,还要向B给出确认。ACK = 1,ack = y + 1,seq = x + 1,此时A进入ESTABLISHED(已建立连接)状态
TCP的连接释放
假设A和B都处于(已连接)状态,A的应用进程 先向其TCP 发出连接释放报文段 ,并停止再发送数据