@TOC
传输层服务概述
概述:
- 传输层协议为运行在不同Host上的进程提供了一种逻辑通信机制
- 端系统运行传输层协议 ①发送方:将应用递交的消息分成一个或多个的Segment,并向下传给网络层。 ②接收方:将接收到的segment组装成消息,并向上交给应用层。
- 传输层可以为应用提供多种协议 ① Internet上的TCP ②Internet上的UDP
传输层 vs 网络层:
- 网络层:提供主机之间的逻辑通信机制
- 传输层:提供应用进程之间的逻辑通信机制 ①位于网络层之上 ② 依赖于网络层服务 ③ 对网络层服务进行(可能的)增强
Internet传输层协议:
- 可靠、按序的交付服务(TCP) ①拥塞控制 ②流量控制 ③连接建立
- 不可靠的交付服务(UDP) ① 基于“尽力而为(Best-effort)”的网络层,没有做(可靠性方面的)扩展
- 两种服务均不保证 ①延迟 ②带宽
复用和分用
概述:
-
接收端进行多路分用: 传输层依据头部信息将收到的Segment交给正确的Socket,即不同的进程
-
发送端进行多路复用 从多个Socket接收数据,为每块数据封装上头部信息,生成Segment,交给网络层。
分用如何工作:
- 主机接收到IP数据报(datagram) ①每个数据报携带源IP地址、目的IP地址。 ② 每个数据报携带一个传输层的段(Segment)。 ③ 每个段携带源端口号和目的端口号
- 主机收到Segment之后,传输层协议提 取IP地址和端口号信息,将Segment导 向相应的Socket
①TCP做更多处理
无连接分用:
- 利用端口号创建Socket
- UDP的Socket用二元组标识 ①目的IP地址 ②目的端口号
- 主机收到UDP段后 ①检查段中的目的端口号 ②将UDP段导向绑定在该端口号的Socket
- 来自不同源IP地址和/或源端口号的IP数据包被导向同一个Socket
面向连接的分用:
- TCP的Socket用四元组标识 ①源IP地址 ②源端口号 ③ 目的IP地址 ④目的端口号
- 接收端利用所有的四个值将Segment导向合适的Socket
- 服务器可能同时支持多个TCP Socket ①每个Socket用自己的四元组标识
- Web服务器为每个客户端开不同的 Socket
UDP
UDP定义:
- 基于Internet IP协议 ①复用/分用 ②简单的错误校验
- “Best effort”服务,UDP段可能 ① 丢失 ②非按序到达
- 无连接 ① UDP发送方和接收方之间不需要握手 ②每个UDP段的处理独立于其他段
UDP为什么存在?
- 无需建立连接 (减少延迟)
- 实现简单:无需维护连接状态
- 头部开销少
- 没有拥塞控制: 应用可更好地控制发送时间和速率
常用于流媒体应用:
- 容忍丢失
- 速率敏感
UDP还用于:
- DNS
- SNMP
在UDP上实现可靠数据传输?
- 在应用层增加可靠性机制
- 应用特定的错误恢复机制
UDP校验和(checksum):
- 发送方 ① 将段的内容视为16-bit整数 ②校验和计算:计算所有整数的和 ,进位加在和的后面,将得到的 值按位求反,得到校验和 ③发送方将校验和放入校验和字段
- 接收方 ① 计算所收到段的校验和 ②将其与校验和字段进行对比
可靠传输
什么是可靠?
- 不错、不丢、不乱
可靠数据传输协议:
- 可靠数据传输对应用层、传输层、链路层都很重要
- 网络Top-10问题
- 信道的不可靠特性决定了可靠数据传输协议(rdt)的复杂性
Rdt 1.0: 可靠信道上的可靠数据传输:
- 底层信道完全可靠 ①不会发生错误(bit error) ②不会丢弃分组
- 发送方和接收方的FSM独立
Rdt 2.0: 产生位错误的信道:
- 底层信道可能翻转分组中的位(bit) ①利用校验和检测位错误
- 如何从错误中恢复? ① 确认机制(Acknowledgements, ACK): 接收方显式地告知发送方分组已正确接收 ②NAK:接收方显式地告知发送方分组有错误 ③发送方收到NAK后,重传分组
- 基于这种重传机制的rdt协议称为ARQ(Automatic Repeat reQuest)协议
- Rdt 2.0中引入的新机制 ①差错检测 ②接收方反馈控制消息: ACK/NAK ③重传
Rdt 2.1和2.2: 如果ACK/NAK消息发生错误/被破坏(corrupted)会怎么样?
- 为ACK/NAK增加校验和,检错并纠错
- 发送方收到被破坏ACK/NAK时不知道接收方发生了什么,添加额外的控制消息
- 如果ACK/NAK坏掉,发送方重传
- 不能简单的重传:产生重复分组
如何解决重复分组问题?
- 序列号(Sequence number): 发送方给每个分组增加序列号
- 接收方丢弃重复分组
Rdt 2.1 vs. Rdt 2.0: 发送方:
- 为每个分组增加了序列号
- 两个序列号(0, 1)就够用,为什么?
- 需校验ACK/NAK消息是否发生错误
- 状态数量翻倍 ①状态必须“记住”“当前”的分组序列号
接收方:
- 需判断分组是否是重复 ①当前所处状态提供了期望收到分组的序列号
- 注意:接收方无法知道ACK/NAK是否被发送方正确收到
Rdt 2.2: 无NAK消息协议:
- 不需要两种确认消息(ACK + NAK)。
- 与rdt 2.1功能相同,但是只使用ACK: ①接收方通过ACK告知最后一个被正确接收的分组 ②在ACK消息中显式地加入被确认分组的序列号
- 发送方收到重复ACK之后,采取与收到NAK消息相同的动作 ①重传当前分组
Rdt 3.0: 如果信道既可能发生错误,也可能丢失分组,怎么办?
- “校验和 + 序列号 + ACK + 重传”不够用。
- 方法:发送方等待“合理”时间 ① 如果没收到ACK,重传 ②如果分组或ACK只是延迟而不是丢了,重传会产生重复,序列号机制能够处理,接收方需在ACK中显式告知所确认的分组。 ③需要定时器
流水线机制与滑动窗口协议:
流水线机制:
- 提高资源利用率
流水线协议:
- 允许发送方在收到ACK之前连续发送多个分组 ① 更大的序列号范围 ②发送方和/或接收方需要更大的存储空间以缓存分组
滑动窗口协议: Sliding-window protocol:
- 窗口 ①允许使用的序列号范围 ② 窗口尺寸为N:最多有N个等待确认的消息
- 滑动窗口 ①随着协议的运行,窗口在序列号空间内向前滑动
- 维持发送方/接收方缓冲区 ①缓冲区是 用来解决网络之间数据不可靠的问题,例如丢包,重复包,出错,乱序
- 滑动窗口协议:GBN(Go-Back-N协议), SR(Selective Repeat协议)
TCP
TCP概述:
- 点对点 ①一个发送方,一个接收方
- 可靠的、按序的字节流
- 流水线机制 ①TCP拥塞控制和流量控制机制设置窗口尺寸
- 发送方/接收方缓存
- 全双工(full-duplex) ①同一连接中能够传输双向数据流
- 面向连接 ①通信双方在发送数据之前必须建立连接。 ②连接状态只在连接的两端中维护,在沿途节点中并不维护状态。 ③TCP连接包括:两台主机上的缓存、连接状态变量、socket等
- 流量控制机制
TCP:序列号和ACK:
序列号:
①序列号指的是segment中第一个字节的编号,而不是segment的编号
②建立TCP连接时,双方随机选择序列号
ACKs:
①希望接收到的下一个字节的序列号
②累计确认:该序列号之前的所有字节均已被正确接收到
接收方如何处理乱序到达的Segment?
- TCP规范中没有规定,由TCP的实现者做出决策
TCP可靠传输
TCP在IP层提供的不可靠服务基础上实现可靠数据传输。
TCP通过序列号、检验和、确认应答信号、重发控制、连接管理、窗口控制、流量控制、拥塞控制实现可靠性。 TCP协议是如何保证可靠传输的
TCP流量控制
流量控制:
- 双方在通信的时候,发送方的速率与接收方的速率是不一定相等,如果发送方的发送速率太快,会导致接收方处理不过来,这时候接收方只能把处理不过来的数据存在缓存区里(失序的数据包也会被存放在缓存区里)。
- 如果缓存区满了发送方还在疯狂着发送数据,接收方只能把收到的数据包丢掉,大量的丢包会极大着浪费网络资源。
- 因此,我们需要控制发送方的发送速率,让接收方与发送方处于一种动态平衡才好。
- 对发送方发送速率的控制,我们称之为流量控制。
TCP连接管理
标志说明:
- ACK:确认序号标志,为1时表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段。
- SYN:同步序号,用于建立连接过程。
- FIN: finish标志,用于释放连接。
TCP连接管理:建立(TCP三次握手):
- 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
- 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
- 握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。
- 理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
从全双工通信的角度理解TCP建立连接为什么要三次握手而不是两次?
- 单纯从浪费网络延迟导致的浪费资源的角度去否定两次握手,感觉这个理由很牵强,这样的浪费三次握手其实也并不能避免。
- 简单化处理 A B的握手细节。突出主要矛盾:
- 如果TCP是两次握手的话:
① 从A的视角来看。“我给B发出一个消息,又收到了回复,那么我可以确定, 我和B之间的通信的路(物理层)是通的”
②A对这个物理链路的理解会是
③但B对这个物理链路的理解
④即B可以确定从A到B这条路是通的,但因为B发给A信息后没有收到A的回复,所以B不能确定是不是从B到A的这条路本身就不通导致自己发发给A的消息根本没有到达。 ⑤在这种情况下,让B确定和A建立连接,是很不明智的。
- 如果是三次握手呢:
①B如果收到了A的回复,那么B就可以确定从我这到A的路是通的。而且也能知道 A是可以确定路是双通的。基于双方都能确定路是双通的,确定建立连接及后续一些操作。
②这和红军蓝军通信没法消除网络猜疑是不同的。 ③三次握手不是为了确定通信的双方能够确定消息的传达,而是确定消息传播的通道是不是畅通的。只要通道是畅通的,可以用其他策略去判断消息是不是准确有序的传递了(消息的序列号,确认号,超时重传等)。
白话版(全双工角度)理解为什么连接建立需要三次握手,而不是两次或四次握手?
-
三次握手: “喂,你听得到吗?” “我听得到呀,你听得到我吗?” “我能听到你,今天balabala……”
-
两次握手: “喂,你听得到吗?” “我听得到呀” “喂喂,你听得到吗?” “草,我听得到呀!!!!” “你TM能不能听到我讲话啊!!喂!” “……”
-
四次握手: “喂,你听得到吗?” “我听得到呀,你听得到我吗?” “我能听到你,你能听到我吗?” “……不想跟傻逼说话”
从安全角度理解为什么连接建立需要三次握手,而不是两次握手?
- 为了防止已经失效的连接请求报文段又突然传到服务端,因而产生错误。
- A发送的一个连接请求在网络结点的时间滞留,以至于延误到连接释放的某个时间才到达B。
- B收到这个请求的报文段后,误以为A又发出了一次新的请求连接,于是向A发送确认报文段,同一建立连接。但是由于A并没有发出新的请求连接, 所以A不会理睬B的确认也不会向B发送数据。
- 但B却认为连接已经建立,一直等待A发来数据。B的资源就白白浪费了。
TCP连接管理:关闭(TCP四次挥手):
- 第一次挥手:客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送,并发送一个自己的ISN(u)
- 第二次挥手:服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(u+1)。同时发送一个自己的ISN(v)
- 第三次挥手:服务器B关闭与客户端A的连接,发送一个FIN、ACK给客户端A,确认号为收到的序号加1(u+1),与上一次不变。同时发送一个自己的ISN(w)
- 第四次挥手:客户端A发送ACK报文确认,并将确认序号设置为收到序号加1(w+1),序列号就是上一次的确认号(u+1)
- TCP连接是全双工的,因此每个方向都必须单独进行关闭。
为什么不是三次挥手或者五次挥手?
- 因为TCP的通信是全双工通信。
- 要实现可靠的连接关闭,A发送结束报文FIN,收到B的确认后。A知道自己没有 数据要发送,B知道A不再发送数据。
- 但是B还可以发送数据,A还可以接收数据。 只有当B发送结束报文FIN,收到A的确认后,才算是真正的断开连接。
拥塞控制原理
拥塞(Congestion)定义:
- 太多发送主机发送了太多数据或者发送速度太快,以至于网络无法处理
表现:
- 分组丢失(路由器缓存溢出)
- 分组延迟过大(在路由器缓存中排队)
端到端拥塞控制:
- 网络层不需要显式的提供支持
- 端系统通过观察loss,delay等网络行为判断是否发生拥塞
- TCP采取这种方法
网络辅助的拥塞控制:
- 路由器向发送方显式地反馈网络拥塞信息
- 简单的拥塞指示(1bit):SNA, DECbit, TCP/IP ECN, ATM)
- 指示发送方应该采取何种速率
TCP拥塞控制
方法:
- 动态调整以改变发送速率
- 反映所感知到的网络拥塞
如何感知网络拥塞?
- Loss事件=timeout或3个重复ACK
- 发生loss事件后,发送方降低速率
如何合理地调整发送速率?
- 加性增—乘性减: AIMD
- 慢启动: SS
总结:4种拥塞控制算法:慢启动,拥塞避免,快速重传和快速恢复。
TCP性能分析
公平性与UDP:
- 多媒体应用通常不使用TCP,以免被拥塞控制机制限制速率
- 使用UDP:以恒定速率发送,能够容忍丢失
- 产生了不公平
公平性与并发TCP连接:
- 某些应用会打开多个并发连接
- Web浏览器
- 产生公平性问题
- eg:链路速率为R,已有9个连接 ① 新来的应用请求1个TCP,获得R/10的速率 ②新来的应用请求11个TCP,获得R/2的速率