2020.4.29晚更新 添加了UDP报文首部中检验和检验比特错的方法
写在前面:
- 最近在复习计算机网络,顺便整理一下看过的东西。一来方便自己复习,二来梳理一下计网核心的脉络。
- 笔者使用的资料是《计算机网络 自顶向下方法》,这份笔记并不能代替对书本的学习,强烈建议看看原书,其中对原理的讲解由浅入深,循序渐进,非常适合入门学习。
- 在整理过程对其中的内容有所取舍并加入了自己的观点,限于个人水平,文中bug在所难免,读者发现还请斧正。
运输层概述
对于运输层的叙述,私下认为可以分为两个部分来阐述。
一是从网络分层的角度,运输层有其需要实现基本功能。
二是运输层也是计算机网络要解决的两个重要的问题。
运输层的最基本功能是将网络层提供的在两个端系统之间的交付扩展到运行在这两个端系统上的应用层进程之间的交付,这是运输层必须实现的功能
- 运输层为应用层提供了逻辑通信功能,即从两个将要通信的应用层进程角度看,它们是仿佛直接相连一般。
- 应用层进程使用逻辑通信功能直接发送报文,而不关注报文传输的物理实现细节。
运输层需要解决的两个问题
- 如何在不可靠的通信链路上实现数据的可靠通信
- 如何实现拥塞控制
运输层与网络层的关系:由于运输层协议只存在于端系统之中
- 运输层提供的服务模型受制于网络层提供的服务。如果网络层协议无法为主机之间运输层发送的报文段提供带宽和时延保证,则运输层也无法为应用层进制之间传输的应用层报文提供带宽和时延保证
- 但运输层可以完善网络层的服务,如在不可靠的网络层服务基础之上提供可靠数据传输
运输层的最基本功能的实现:多路复用/分解
套接字是应用层进程与运输层之间的软件接口(一扇门),运输层通过套接字来交付数据
将主机间的交付扩展到进程间的交付即运输层的多路复用与多路分解,这是任何一个运输层协议必须实现的功能
多路复用:运输层收集来自应用层中不同套接字的数据,并封装首部信息(用于分解)而形成报文段
多路分解:运输层将报文段的数据正确交付到不同的套接字
运输层多路复用的要求:
- 套接字有唯一的标识符(这就是端口号)
- 每个报文段都有一个字段来标识其需要交付到的套接字,即运输层报文中有源端口号和目的端口号字段
端口号是一个16bit的数,范围为0~65535,其中0~1023为周知端口号,用于周知应用层协议,其余端口号由主机自由分配
运输层协议是如何扩展网络层端系统之间的交付服务的?
在主机的每个套接字都能分配到一个端口号,发送方将来自不同端口号的应用层报文封装其首部(添加源端口号和目的端口号)而形成报文段,传递到网络层,接收端根据网络层传递的报文段的目的端口号将其交付给对应端口号的套接字,从而实现应用进程之间的交付。
无连接的多路复用与多路分解
即UDP的多路复用/分解
UDP套接字通过一个二元组来全面标识,其包括目的IP地址和目的端口号
注意:来自不同源的报文段如果有同一个目的套接字,则其会交付给同一个应用层进程
面向连接的多路复用与多路分解
即TCP的的多路复用/分解
TCP的套接字由一个四元组来全面标识,包括源IP地址、源端口号、目的IP地址、目的端口号
TCP的套接字还标识了一个TCP连接,当客户端敲欢迎之门时,欢迎之门会为不同TCP套接字的请求分配不同的端口号
注意:套接字不同,则TCP连接不同,即使有相同目的IP地址、目的端口号,而源不同的TCP链接,其传输的报文段也会发往不同的进程,这是与UDP套接字的细微差别
实际上,连接套接字与服务器进程并非一一对应的关系,当今的服务器往往只运行一个进程,但是为每个新的客户链接分配一个有新链接套接字的线程
无连接运输:UDP
IP层提供尽力而为的交付服务,即它在网络层尽最大努力交付报文段,而不提供任何保证
UDP是运输层的最简协议,它不提供不必要的服务,换言之,UDP只提供了运输层的必要服务——多路复用与分解
如果应用程序使用了UDP作为运输层协议,则应用层报文几乎直接与网络层打交道
UDP与TCP的区别、UDP为什么适用
- 关于发送什么数据以及何时发送数据的控制更为精细 采用UDP时,只要应用层报文传递给UDP,UDP会立刻将报文封装成UDP报文段,并立即传递给网络层。而TCP连接由于其拥塞控制,在链路拥塞时会抑制TCP发送方的发送。实时应用通常要求最小发送速率且可以容忍一定的数据丢失,而不希望延迟报文段的发送。
- 无需链接的建立 UDP在发送数据之前,无需任何准备即可进行数据传输。而TCP开始传输数据之前要进行三次握手,从而引入了建立链接的时延。
- 无连接的状态 TCP要在端系统维护TCP链接的状态,包括发送、接受缓存,报文序号和确认号参数,而UDP不需要维护这些变量。
- 分组首部开销小 UDP首部8字节,TCP首部20字节。
UDP报文段结构与UDP检验和
长度:长度为UDP数据报的长度,即首部+应用层报文
检验和:发送方将UDP的所有16比特字(言下之意报文也会参与计算)进行求和,最后取其反码,求和时遇到最高位溢出时,则对其进行回卷(如1101 + 1000,计算后得到0101且得到一个最高位溢出的进位,这时我们将这个进位给到最低位,即相当于0101 + 0001 = 0110)
(2020.4.29更新)
得到UDP检验和后,你可能会想,接收方是如何通过检验和发现报文出现比特错的呢?
回答这个问题之前,我们不妨试着将UDP报文段各个16比特字相加。为了简化问题,这里用我们说明回卷的例子做个实验,即对于1101和1000,其“检验和”为1001(别忘记取反),我们将这三个二进制数相加,即1101 + 1000 + 1001 = 1110 和一个最高位的进位,我们对其回卷,即相当于1110 + 0001 = 1111,怎么样?你是不是看出门道了?
没错,如果传输过程没有出现比特差错,对UDP中每个16比特字数据进行求和(包括检验和)并回卷,我们可以得到1111 1111 1111 1111,接收方即可以认为该分组在传输过程中没有发生比特差错。