本笔记中的大部分来自01大学海牛学长,笔记中引用部分为自己的感悟,请斟酌查看。
01星球:https://space.bilibili.com/1653229811
温馨提示:由于笔记的图床位于github,若是想查看图片需要魔法上网。
# 第一章 计算机网络基础
计算机网络由若干节点和链接这些节点的链路组成
- 主机(host)、端系统(end system)
- 端系统通过通信链路(communicate link)和分组交换机(packet switch)的网络连接在一起
- 通信链路,不同的物理媒介组织的传输数据,以传输速率bit/s进行度量
- 分组交换机主要由路由器(router)和链路层交换机(link-layer switch)
主机和端服务的区别: 从学习计算机网络的角度看,这两者大致相等,就像我们平时在说在的“端到端的系统通信”、“主机到主机的通行”理解起来是一个意思,但其实两者存在包含关系端服务器包含主机。只是主机更加侧重主机这一主体,而端服务设备在网络中的位置( 边缘结构 )和其作为数据通信端点的功能。
通信链路和分组交换机: 从某种意义上来说,计算机网络对数据传输研究的就是这两个东西,通信链路就是链接两个或多个设备的物理通道或者逻辑路径,而分组交换机类似于是一个中转站,将传输的数据从一条通信链路链接到另一条通信链路上。
边缘结构:网络的外围部分,包括用户设备、接入点以及边缘服务器等。
核心结构:核心结构指的是网络的中心部分,通常包括高性能的路由器、交换机和数据中心,负责管理和转发大量的数据流。
理解网络、互联网、因特网的区别
- 网络是一个大的概念,由节点和链路构成的都可以称为网络。节点的涵盖范围很大如机顶盒、车载导航等而链路分为有线和无线。
- 互联网就是各种网络互相之间的数据通信。各个异构网络由路由器相连,由于每个网络群之间不同类型的网络技术和架构通过路由器可以链接多个异构网络
- 因特网最要是提供了IP地址,IP可以看作为一种身份信息,可以参与万维网。因特网是当今世界上最大的互联网。
- 局域网:一般指的是范围在几百到几公里办公楼或者校园内计算机相互连接成的计算机网络,一般用在狭小区域内的网络,一个社区、一栋楼、办公室经常使用局域网。
- 城域网:一个城市中的计算机所相互连接形成的计算机网络。城域网是介于广域网与局域网之间的一种高速网络。城域网设计的目标是要满足几千米范围内的大量企业、机关、公司的多个局域网互联的需求,以实现大量用户之间的数据、语音、图形与视频等多种信息的传输功能。
- 广域网:广域网中的计算机所形成的连接范围就更大了,常常是一个国家或是一个洲。其目的是为了让分布较远的各局域网互联。
# 1.1 计算机网络的发展史
简单阐述
ARPA ARPANET(阿帕网) TCP协议和IP协议 1966 --------------------------》 1974 ------------------》 后续不停完善( 其实一开始使用的4层协议,后来人们根据OSI的7层模型进行一定修改改为5层模型 )。
OSI在1986年在ARPA的基础上发表7层模型的标准。这个模型几乎做到了无懈可击,但是由于公司习惯了TCP协议和IP协议且由于7层模型过于复杂,所以现在几乎没有使用7层模型,只有在平时研究时会使用。
计算机网络的进一步发展是1993年依托Internet的WWW(万维网)的出现发生了突破使人们在网络中看到的不仅仅是文字,更能看到视频图片等内容。
# 1.2 OSI七层结构和TCP/IP协议结构
OSI当年提出七层参考模型,作为计算机网络法律标准,但是由于当时已经有大量的公司用了TCP/IP参考模型结构,且OSI的七层结构过于复杂所有不适用于公司的生产。而在平时公司中若要使用TCP/IP协议基本用的都是4层模型。且一般不会关注网络接口层( 也就是平时我们在说的网卡 ),一般都是重视上三层。而便于学习,平时学习过程中基本都是使用5层结构,分离出来的数据链路层是便于我们对各种协议的理解,这些协议的思想在后续的层仍然会有部分使用。
OSI标准失败的原因:
- 缺乏实际经验,没有商业驱动力
- 协议实现过分复杂,运行效率很低
- 标准的制定周期太长,产品无法及时进入市场
- 层次划分不太合理,有些功能在多个层次中重复出现
# 物理层要考虑的问题
- 采用什么传输媒介 (介质)
- 采用什么物理接口
- 采用什么信号表示比特0和比特1
物理层是电子层面的一般使用IEEE规范,表示比特0和比特1会有很多的情况要按照固定的标准,计网的考察的时候很少会涉及到这一层。
# 链路层考虑的问题
- 标识网络中各主机的身份 (例如MAC地址)
- 从比特流中区分出地址和数据 (数据封装格式)
- 协调各主机争用总线 (媒体接入控制)
- 以太网交换机的实现 (自学习和转发帧)
- 检测数据是否误码 (差错检测)
- 出现传输差错如何处理 (可靠传输和不可靠传输)
- 接收方控制发送方注入网络的数据量 (流量控制)
其实到了链路层就是说是组成了一个网络,而在链路层上方的是对于TCP/IP的使用做的规范。在这一层我们要解决当主机接收到数据时我们需要判断这个数据是哪个主机传过来的,接着我们就要想这个数据到底可不可靠呢?这个涉及到是否是可靠传输( 不一定不可靠传输就是不好的,只是使用条件不同 )。我们在传输过程中需要一根主线,这跟主线分出支线来连接主机。还需要对传输数据的速度做一定的规范,不然传输速度过快也会导致主机读不过来。
# 网络层需要考虑的问题
- 标识网络和网络中的各主机 (网络和主机共同编制,例如IP地址)
- 路由器转发分组 (路由选择协议、路由表和转发表)
网络层需要实现给每个主机赋予IP地址,这个是参与因特网的身份证,毕竟没有这个身份证,数据传输到别的主机都不知道是哪个主机传过去的。其外网络还需要完成路由器对数据的转发,正确的转发数据。
# 传输层需要考虑的问题
- 进程之间基于网络的通信 (进程的标识,例如端口号)
- 出现传输差错如何处理 (可靠传输和不可靠传输)
传输层首先要解决的就是当数据传到电脑上后,到底这个数据是给电脑的哪个软件进行使用,这个时候就依托到了端口号,端口号是一种进程的标识符。在此同时我们也要判断数据的内容是否正确,数据传输的方式是否可靠从而引出TCP/UDP,前者是可靠传输的端口协议,后者是不可靠传输的端口协议。事实上这一层最重要的是端口协议,只是平时的教学把目光集中于TCP/UDP,考题也多为这个方面。
# 应用层需要考虑的问题
- 不同的数据格式、数据解析、数据处理
# OSI七层结构每层的主要作用
# 1.3 计算机网络的数据传输
# 电路交换
- 建立连接,分配通信资源
- 通话,一直占用通信资源
- 释放连接,归还通信资源
电路连接首先会将双方的主机进行连接,连接后这个线就会被这两个主机占用。在占用期间会进行数据的传输,直到传输完毕才会把连接断开,这条连接的线路占用的资源会被释放。
# 分组交换
分组转发是将一个大的文件拆分为多个小文件,那么路由器在转发的途中如何知道这个小文件要转发到哪里呢,为了解决这个问题,提出了首部的概念。当一个大文件被拆分为小文件时会在小文件上加上首部,首部存放的信息帮助路由器将文件传输到指定的位置。同时由于分组传输的性质,没办法确保小文件到达的顺序,那从小文件拼接为大文件也依托于首部中的信息。
- 优点
- 没有建立连接和释放连接的过程。
- 分组传输过程中逐段占用通信链路,有较高的通信线路利用率。
- 交换节点可以为每一个分组独立选择转发路由,使得网络有很好的生存性。
- 缺点
- 分组首部带来了额外的传输开销
- 交换节点存储转发分组会造成一定的时延
- 无法确保通信时端到端通信资源全部可用,在通信量较大时可能造成网络阻塞
- 分组可能会出现失序和丢失等问题
# 两者对比
# 1.4 计算机网络的性能指标
# 速率
- 数据量的常用单位有字节(byte,记为大写B)
- 速率是指数据的传送速率(即每秒传送多少个比特),也称为数据率 (Data Rate)或比特率 (Bit Rate)
- 速率的基本单位是比特/秒 (bit/s,可简记为b/s,有时也记为bps,即bit per second)
- 数据量单位中的K、M、G、T的数值分别为2^10^、2^20^、2^30^、2^40^
- 速率单位中的k、M、G、T的数值分别为10^3^、10^6^、10^9^、10^12^
从上述题目的描述中可以看出尽管数据量和速率在单位的使用上字母相同但是实际意义和数字是完全不同的,数据量以一个字节作为起始量,而速度是以
1
为起始量。所以在做题计算时间时要注意数据量的转换。
# 带宽
- 带宽在模拟信号系统中的意义,某个信号所包含的各种不同频率成分所占据的频率范围。单位: HZ
- 带宽在计算机网络中的意义,用来表示网络的通信线路所能传送数据的能力,即在单位时间内从网络中的某一点到另一点所能通过的最高数据率。单位: b/s。
- 数据传送速率=min[ 主机接口速率,线路带宽,交换机或路由器的接口速率 ]
带宽这个概念在电子领域和计算机领域都存在并且表示的意思不同,在电子领域,带宽表示信号频率(kHZ),在计算机领域表示通信的线路所能传送的数据的能力(kb/s)。
数据传输速率遵从短板效应,在主机接口速率,线路带宽,交换机或路由器的接口速率中最慢的决定数据传输速率。从家里的网络举例,决定网速的不仅仅是营业厅来推销的百兆网线,这个仅仅是线路的带宽,还取决于主机的接口速率,也就是电脑的网卡的类型,最大的接受效率。也取决于路由器的性能,是否兼容线路带宽。
# 吞吐量
- 吞吐量是指在单位时间内通过某个网络或接口的实际数据量。吞吐量常被用于对实际网络的测量以便获知到底有多少数据量通过了网络。
- 吞吐量受网络带宽的限制
吞吐量是图中画线的总和而不是线路带宽。
# 时延
- 时延是指数据从网络的一端传送到另一端所耗费的时间,也称为延迟或迟延。数据可由一个或多个分组、甚至是一个比特构成。
- 分为:发送时延、传播时延、排队时延、处理时延
上图表示了数据在传输过程中每个阶段产生的时延,在考试的计算中一般会省略排队时延和处理时延,从图中可以看出后半部分并没有画,但这并不是没有时延,而是后半部分就是前半部的再一次运作,也就是说当路由器或者交换机处理完成数据后传输到下一个主机又要经历一次发送时延、传播时延、排队时延、处理时延的过程。
需要较好的理解上面的两副图,特别是第二幅是考试中考察时延的常见题。首先对第一幅图进行一下说明。第一次看到这图可能较为疑惑的是为什么分组是斜的。那是因为分组在传播中是连续的而非间隔的。说人话就是边发边传,所有只有走完发送时延才会进入传播时延。这一点在图二中的表现更为明显。而在图二中最需要注意的就是路由器的发射延迟比主机A的发送时延低很多,从中可以看出时延是阶段性的,只有完成前一个时延才能进入下一个时延。
# 时延带宽积
- 时延带宽积是传播时延和带宽的乘积。
- 链路的时延带宽积也称为以比特为单位的链路长度,这对我们以后理解以太网的最短帧长是非常有帮助的
我们可以将带宽理解成马路,假如政府修建了一条马路,希望马路人多还是人小呢。显然是希望人多更加的好。那么带宽也是一样的道理,若是以太网的最短帧过于的短,那么就难以占慢带宽,造成浪费。
# 往返时间
- 往返时间(Round-Trip Time,RTT)是指从发送端发送数据分组开始,到发送端收到接收端发来的相应确认分组为止,总共耗费的时间。
显而易见的是距离越远往返时间就越短。
# 利用率
- 链路利用率,链路利用率是指某条链路有百分之几的时间是被利用的(即有数据通过)。完全空闲的链路的利用率为零
- 网络利用率,网络利用率是指网络中所有链路的链路利用率的加权平均
# 1.5 计算机网络数据封包和解包
封包和解包是数据能准确传输的关键。一个数据从应用层就是开始增加首部接下来的每一次都会增加一个首部,在链路层更会增加一个尾部。需要注意的是当传输到路由器时会进行解包将主机链路层封的包解开,然后在对其封包,来达到转发的目的。然后传输到服务器,接着自下而上进行解包最终到达应用层,将数据传输到指定的应用。
# 1.6 网络体系的术语
实体、协议、服务
实体
- 实体是指任何可发送或接收信息的硬件或软件进程
- 对等实体是指通信双方相同层次中的实体
协议
- 协议是控制两个对等实体在“水平方向”进行“逻辑通信”的规则的集合
- 协议的三要素
- 语法,定义所交换信息的格式
- 语义,定义通信双方所要完成的操作( 如三次握手 )
- 同步,定义通信双方的时序关系
服务
- 协议是“水平”的,而服务是“垂直”的
- 实体看得见下层提供的服务,但并不知道实现该服务的具体协议。下层的协议对上层的实体是“透明”的。
- 对等层次之间传送的数据包称为该层的协议数据单元(Protocol Data Unit,PDU)
- 同一系统内层与层之间交换的数据包称为服务数据单元 (Service Data Unit,SDU)。
# 第二章 计算机网络互联
# 2.1 计算机之间的连接方式
单工,全双工,半双工的区别
- 单工 发送端、接收端 设备只具备一种能力
- 全双工 发送端、接收端 设备具备两种能力
- 半双工 发送端、接收端 设备具备两种能力 信道只有一根 同时只能满足一个通信过程
# 2.1.1 两台计算机互联
- 网线直连
- 需要用交叉线(不是直通线)
需要注意计算机的网络接口上有管脚,管脚上有传入传出的管脚。若使用直通线,试想从一个主机的发送口给另一个主机的发送口发消息,这行得通嘛?而交叉线就解决了这个问题。
# 2.1.2 多台计算机的互联(旧式)
- 同轴电缆
- 连接模型,左右扩散
- 连接特点 :
- 半双工通信、容易冲突
- 不安全、一旦某段线路出现问题,整个通信网络都会瘫痪
图中有一个终结电阻。这个电阻的作用是当数据在电缆中传播的时候,为了防止数据一直在电缆中占用电缆,毕竟电缆是半双工的,当有数据占用了电缆,其他的数据就不能使用电缆了。
# 2.1.3 多台计算机的互联 --- 集线器(Hub)
集线器有多个接口,接口的类型是RJ-45
。⼀个接口收到数据后会发给其它的全部接口。集线器工作在物理层,类似于⼀个多接口的转发器,收到什么就转发什么,⼀个接口收到会转发给其它的全部接口。
连接模型
连接特点
- 半双工通信、容易发生冲突
- 不安全、跟同轴电缆一样,没有记录存储能力,但某两个节点出现问题,不影响其他节点
缺点
- 如果有1000台设备用多集线器连接,那么1台主机发送的数据,虽然最后只有一个主机来处理这个数据包,但会被发送到999台主机,对整个网络链路的占用率会非常高。
集线器是“没有脑子的”,所以在输出过程中会以广播的形式向所有的主机进行发送数据。比如上图中计算机1向计算机2发送数据,当数据通过集线器时,集线器会向计算机2和计算机3都发送数据包,当计算机2接收到数据包要向计算机1返回数据包经过集线器,同样的集线器会向计算机1和计算机3发送数据包。
# 2.1.4 多台计算机的互联 --- 网桥(Bridge)
网桥又叫做桥接器,工作在数据链路层,是一个二层设备。网桥能够互连两个采用不同传输介质与不同传输速率的网络,但是网桥需要互连的网络在数据链路层以上采用相同的协议。网桥可以分隔两个网络之间的通信量,对收到的帧根据其MAC帧的目的地址进行转发和过滤。当网桥收到一个帧时,并不是向所有的接口转发此帧,而是根据此帧的目的MAC地址,查找网桥中的地址表,然后确定将该帧转发到哪一个接口,或者是把它丢弃(即过滤)。
通信流程
特点
- 网桥可以通过自学习得知每侧接口的MAC地址,从而起到隔绝冲突域的作用
网桥”有脑子“了,但是网桥只有两个接口。以上图为例,当计算机1要向计算机3发送数据包。计算机1会先发一个
ARP
包( 后续会讲到 )确定计算机3的位置,即在网桥的左侧还是右侧。当计算机3接收到ARP
包返回计算机1当数据包到达网桥时,数据包并不能通过网桥到达集线器1,因为之前网桥已经记住了计算机的MAC
地址( 后续会讲到 )。接着计算机1发送数据包,当数据包到达网桥同样通过不了网桥,因为网桥已经记住了计算机3的MAC
地址。
# 2.1.5 多台计算机的互联 --- 交换器(Switch)
相当于集线器+网桥,接口更多的网桥、全双工通信,比集线器安全
- 通信流程
交换器融合了集线器和网桥,也就是“有脑子”的集线器。需要注意的是和网桥相同的是交换器记忆的任然是
MAC
地址,而非IP
的地址,所以知道交换器,之前的所有的设备都存留在数据链路层。那么需要思考的是是非世界的主机都可以用交换机进行连接吗。首先理论上来说基于交换机的性质这是可行的。但是在实际实践的过程中会存在一些问题如不方便管理,没有跨区功能,大量的ARP
请求。
# 2.1.6 多台计算机的互联 --- 路由器(Router)
- 之前的多台计算机互联,连接的设备必须在同一网段,处在同一广播域
- 路由器的特点
- 可以在不同网段之间转发数据
- 隔绝广播域
路由器解决了交换机的问题,路由器可以用来解决跨域的问题,与交换机不同的是路由器记忆的是
IP
地址。而且在使用路由器的时候,路由器的每个接口都要配置IP地址来作为一个区块的网关( 注意这里的IP
不能与前边的IP
重复,同时要给每个计算机设置网关 )。比如上图计算机0向计算机2发送数据会先发送ARP请求,此时ARP
包要寻找网关的位置,所以其实这个ARP
请求寻找的IP
为192.168.1.1
( 这是网关地址 )的地址。当计算机0发出的包不属于自己网段,那么计算机0都会将这个包丢向网关IP
所在的地址。
# 2.2 MAC地址
# 2.2.1 MAC地址的格式特征
每一个网卡都有一个6字节(48bit)的
MAC
地址(Media Access Control Address),MAC
地址的结构如下全球唯一,固化在网卡的
ROM
中,由IEEE802
标准规定- 前3字节:
OUI
,组织唯一标识符,由IEEE
的注册管理机构分配给厂商 - 后3字节: 网络接口标识符,由厂商自行分配
- 前3字节:
MAC
地址的表示格式Windows: 40-55-82-0A-8C-6D
- Linux、Android、Mac、iOS: 40:55:82:0A:8C:6D
- Packet Tracer: 40.55.82.0A.8C.6D
- 当48位全为1时,代表广播地址: FF-FF-FF-FF-FF-FF
查询
OUI
的网址https://standards-oui.ieee.org/oui/oui.txt https://mac.bmcx.com/
# 2.2.2 MAC地址的获取
- 当不知道对方主机的
MAC
地址时,可以通过发送ARP
广播获取对方的MAC
地址- 获取成功后,会缓存IP地址、MAC地址的映射信息,俗称: ARP缓存
- 通过ARP广播获取的MAC地址,属于动态 (dynamic) 缓存
- 存储时间比较短(默认是2分钟),过期就自动删除
- 相关命令
- arp -a[主机地址]: 查询ARP缓存
- arp -d[主机地址]: 删除ARP缓存
- arp -s 主机地址 MAC地址: 增加一条缓存信息 (这是静态缓存,存储时间较久)
建议不要轻易尝试使用第三条指令,防止出现不可预料的问题。
# 2.2.3 ARP
ARP
协议的全称是 Address Resolution Protocol(地址解析协议),它是一个通过用于实现从IP
地址到 MAC
地址的映射即询问目标 IP
对应的 MAC 地址的一种协议。ARP
协议在IPV4
中极其重要
根据上图来讲解一下
ARP
,其实前面已经提到了很多次ARP
了假设计算机A要向计算机B发送一个数据包,那么要对数据包进行分装直到网络层,我们知道计算机B的
IP
地址为192.168.1.11
,那么接着往下一层进行移动,移动到链路层只知道计算机A的MAC
地址,并不知道计算机B的MAC
地址,所以这样的话就要发送ARP
请求,注意这个请求是以广播的方式发送。ARP
不仅仅包括出发地和目的地的MAC
地址,也包含一个数据域,当然其中存放的不是像我上面写的那样,其实以其他的方式来表示,上述的表示只是为了方便阐述。当计算机B接收到ARP
请求后,发送ARP
响应。APR
响应中包含计算机A和计算机B的MAC
地址的信息。需要注意的是当ARP
请求完成后,计算机A和计算机B双方都记住了对方的MAC
地址,当后续计算机B要向计算机A发送数据包就不需要再次发送ARP
( 当然前提是ARP
缓存没有被清除)。
# 2.2.4 ARP缓存
通过ARP
缓存,降低了网络流量的使用,在一定程度上防止了 ARP
的大量广播。
一般来说,发送过一次 ARP
请求后,再次发送相同请求的几率比较大,因此使用 ARP
缓存能够减少ARP
包的发送,除此之外,不仅仅 ARP
请求的发送方能够缓存 ARP
接收方的 MAC
地址,接收方也能够缓存ARP
请求方的IP
和MAC
地址,如下图所示。
# 2.2.5 RARP
与ARP
相对的,RARP
(Reverse Address Resolution Protocol) 是将ARP
反过来,从MAC
地址定位IP
地址的一种协议,将打印机服务器等小型嵌入式设备接入网络时会使用到。( 目前被BOOTP、DHCP所取代。)
# 2.3 IP地址
现如今有两个版本的 IP
地址,IPv4
和 IPv6
,现在广泛应用的是IPV4
,IPV4
由32
位组成,在计算机中用二进制来处理。但是为了增加易读性,将32
位以8
位为一组进行十进制的转化。
IP
地址的总个数有 232
次幂个,这个数值算下来是4294967296
到网络。大概能允许 43
亿台设备连接。但是决定IP
不会以主机的个数来配置的,而是根据设备上的 网卡(NIC
) 进行配置。
有了
MAC
地址了为何还要IP
地址呢,这个原因在之前MAC
中已经有所提到。
- 当发送数据包,
ARP
缓存表中没有对应目的地址的ARP
缓存。那么就会发送ARP
广播,那么就会引发广播风暴。- 若只是用
MAC
地址没办法做到区域的隔离。MAC
是唯一的,就像是身份证号码一样,试想若是身份证号码是杂乱无章那就很不便于管理,而MAC
就像是杂乱无章的号码一样,不便于管理。
# 2.3.1 IPV4的表示方法
IPV4
地址的编址方法经历了三个历史阶段:
虽然说前面两种已经淘汰,但是现今的无分类编址是在前两者分离出来的。
IPv4
地址的分类编址方法
- 网络层如何识别一个设备的信息,就像人一样,有身份证那样
- 早期为了分类管理,采用了下表的固定方式进行分类管理
- A类、B类和C类地址都是单播地址,只有单播地址可以分配给网络中的主机 (或路由器)的各接口。
- 主机号为“全0”的地址是网络地址,不能分配给主机 (或路由器) 的各接口。
- 主机号为“全1”的地址是广播地址不能分配给主机(或路由器) 的各接口。
- 单播:主机到主机
- 广播:网络号内进行全部通知 如ARP
- 组播/多播:这个要用到上述的D类地址,如要把
c1
和c2
一起传出去,就要执行类似c1 c2 add
组播IP地址的形式
- 一般不使用的特殊
IPv4
地址
# 2.3.2 IPv4地址的划分子网编址方法
随着更多的中小网络加入因特网,IPv4
分类编址方法不够灵活、容易造成大量IP4地址资源浪费的缺点就暴露出来了。分类编址方法不够灵活且容易造成大量地址浪费,划分子网编址方法对其进行改进(“打补丁”)。
- 子网掩码可以表明分类
IPv4
地址的主机号部分被借用了几个比特作为子网号。 - 与
IPv4
地址类似,子网掩码也是由32
比特构成的。- 用左起多个连续的比特
1
对应IPv4
地址中的网络号和子网号 - 之后的多个连续的比特
0
对应IPv4
地址中的主机号
- 用左起多个连续的比特
- 只要给定了一个分类的
IPv4
地址及其相应的子网掩码,就可以得出子网划分的全部细节
对于子网掩码来说
- 网络号:IP地址 和 子网掩码相与
- 主机号:IP地址和子网掩码取反相与
划分子网
将IP地址中的主机号部分再拿出某几位来作为网络号,剩下的部分作为主机号 。
下面看⼀个例子:
现有一个C类网210.55.23.X。由于有四个不同的部门要使用这段IP,为了不让各个部门之间相互干扰,我们需要如何处理?
做这类题时需要主要要减去全
1
和全0
的情况,所以在最后算出来有多少个数时往往要减去2
,子网掩码的计算我个人推荐是转化到二进制去观察,自己在脑子里想很容易思考错误。做题时可以借助以下网站来验证自己答案
在线⼯具:https://tool.chinaz.com/tools/subnetmask
# 2.3.3 IPv4地址的无分类编址方法
若是对分类编址和划分子网比较熟悉,那么对于无分类编制方法就很好理解,也就是把分类编制的类型这一限制去除。
为了简便起见,可以不明确给出配套的地址掩码的点分十进制形式,而是在无分类编址的IPv4
地址后面加上斜线“/”,在斜线之后写上网络前缀所占的比特数量 (也就是地址掩码中左起连续比特1
的数量),这种记法称为斜线记法
# 2.3.4 构造超网
- 原本有
200
台计算机使用192.168.0.0/24
网段,现在希望增加200台设备到同一个网段。200
台在192.168.0.0/24
网段,200
台在192.168.1.0/24
网段- 合并
192.168.0.0/24
、192.168.1.0/24
为一个网段:192.168.0.0/23
(子网掩码往左移动1
位)
超网和子网相对应。划分子网是增加网络部分的位数,减少主机部分的位数;构建超网是减少网络部分的位数,增加主机部分的位数。基于现如今
IPV4
的无分类编址方式,不论在划分子网还是在构建超网,都要先算好子网掩码,这个是区分网络部分和主机部分的关键。
路由聚合
- 网络前缀越长,地址块越小,路由越具体;
- 若路由器查表转发分组时发现有多条路由条目匹配,则选择网络前缀最长的那条路由条目这称为最长前缀匹配,因为这样的路由更具体。
路由聚合和构造超网的一种应用,需要明白的是我们的路由器同样也是一个电脑,在其中跑着操作系统,有着自己的存储空间,但是这个存储空间非常的小,若是像上表将所有网络都存放下来,那对于路由器是一个很大的负担,所以通过路由聚合的方式可以很大程度上的节约路由器的内存空间。
由上图可知,5个网络的下一跳的目的地都相同,而且有着共同前缀,所以可以将这些网络在路由表中用聚合地址块的形式存储下来。
子网和超网的判断
- 先判断该网段的类型,是A类、B类、C类网络
- 默认
A
类子网掩码的位数是8
,B
类子网掩码的位数是16
,C
类子网掩码的位数是24
- 默认
- 然后判断子网掩码的位数
- 比默认子网掩码多,就是子网
- 比默认子网掩码少,就是超网
# 2.4 路由概述
# 2.4.1 路由的作用
在不同网段之间转发数据,需要有路由器的支持
默认情况下,路由器只知道跟它直连的网段,非直连的网段需要通过静态路由、动态路由告诉它
静态路由
管理员手动添加路由信息
适用于小规模网络
动态路由
- 路由器通过路由选择协议 (比如RIP、OSPF) 自动获取路由信息
- 适用于大规模网络
路由在上述中已经提到过了多次,在路由这个章节讲的都是在同一个局域网内进行操作,而两个网段要是想进行通行就要通过路由。
# 2.4.2 多个不同网络段的互联互通
上图中有四个网段,四个网段通过了两个路由器进行连接,要在两个路由器连接网络的四个接口填入四个网络的网关,而图中两个路由器用红线进行连接,这个是骨干网连接线,这两个接口也要配置IP,需要注意这俩个IP要在同一个网络中,但是又不能和其他四个主机在同一个网络中。
关于路由器下一跳的书写,下述中的网络填写的就是接入口的网络,而下一跳就是写要从路由器的哪个出去,题目中一般会以
192.168.1.0/24 via 172,16.18.3
来展示添加的静态路由。
现在假设从计算机0向计算机2发送数据,要先发送
ARP
请求,找到路由器0,接着返回到计算机0。接着向路由器发送文件包,路由器0通过路由表将数据传给路由器1,但是由于路由器1并不认识计算机2,所以路由器会发送ARP
请求,同时会直接丢弃掉文件包。等第二次计算机1向计算机2发送数据就畅通无阻了。若使用ping
指令会出现以下情况。
# 2.4.3 数据包的传送过程
- 在数据包的传送过程中,数据包的源IP地址和目的IP地址保持不变。
- 在数据包的传送过程中,数据包的源MAC地址和目的MAC地址逐链路 (或逐网络)改变。
# 2.5 因特网的公网和私网
# 2.5.1 因特网的接入方式
电话线入户
- 平时说的ADSL电话拨号上网,非对称数字用户线路,提供上、下行不对称的传输带宽
- 需要提供猫(Modem),调制解调器,进行数字信号和模拟信号的转换
光纤入户
- 光猫 (optical modem) ,光调制解调器,进行数字信号和光信号的转换
叫猫或者光猫其本身和猫没关系,仅仅是因为
modem
这个单词读音比较像猫而已。电话线入户现在基本淘汰,收到物理层面的限制,根本达不到现在的百兆。现在用的都是光纤到户,平时可以看到住房有拔地而起的很多线连接着屋顶,这些就是光纤。
# 2.5.2 公网和私网
- 公网
Internet
上路由器中只有到达公网的路由表,没有到达私网的路由表- 公网
IP
由因特网信息中心 (Internet Network information Center,Inter NIC) 统一分配和管理 ISP
需要向Inter NIC
申请公网IP
- 私网
- 主要用于局域网
- A类:
10.0.0.0/8
,1
个A类网络 - B类:
172.16.0.0/16~172.31.0.0/16
,16
个B类网络 - C类:
192.168.0.0/24~192.168.255.0/24
,256
个C类网络
网络地址分成私网和公网,边缘网络设备使用私网能进行内部通讯,骨干网设备(路由器) 不允许转发私网
TP
# 2.5.3 NAT技术
- 私网
IP
访问Internet
需要进行NAT
转换为公网IP
NAT
(Network Address Translation)- 这一步可以由路由器来完成
- NAT特点
- 可以节约公网
IP
资源 - 会隐藏内部真实
IP
- 可以节约公网
- NAT分类
- 静态转换,手动配置NAT映射表
- 动态转换,定义外部地址池,动态随机转换,一对一转换
PAT
(Port Address Translation),多对一转换- 采用端口多路复用技术
用户用的都是私网
IP
,这个IP
只是在用户所在的局域网内是身份证,若是要连接局域网,会在路由器通过NAT
技术将IP
地址进行转化来连接到因特网。NAT有三种类型,其一是一个私网
IP
绑定一个公网IP
,这种显然不能解决IP
地址不足的问题。其二是当一个私网IP
要上因特网时就分配一个公网IP
给它。第三个是现在普遍使用的方法,一个公网对应了很多的端口,用端口对接用户私网中要连接因特网的软件。
# 第三章 链路层
# 3.1 数据链路层概述
- 链路 (Link)是指从一个节点到相邻节点的一段物理线路 (有线或无线),而中间没有任何其他的交换节点。
- 数据链路 (Data Link)是基于链路的。当在一条链路上传送数据时,除需要链路本身,还需要一些必要的通信协议来控制这些数据的传输,把实现这些协议的硬件和软件加到链路上,就构成了数据链路。
- 不同类型的数据链路,所用的通信协议可能是不同的
- 广播信道:
CSMA/CD
协议 (比如同轴电缆、集线器等组成的网络) - 点对点信道:
PPP
协议 (比如2个路由器之间的信道)
- 广播信道:
- 计算机中的网络适配器 (俗称网卡) 和其相应的软件驱动程序就实现了这些协议。一般的网络适配器都包含了物理层和数据链路层这两层的功能
上述中的广播信道应用之一就是
ARP
,而点对点就是两个路由器之间进行通行。
# 3.2 数据链路层的三个问题
# 3.2.1 封装成帧
- 帧(Frame)的数据部分,就是网络层传递下来的数据包(IP数据包,Packet)
- 最大传输单元MTU(Maximum Transfer Unit)
- 每一种数据链路层协议都规定了所能传送的数据长度上限
- 以太网的
MTU
为1500字节
- 以太网V2的MAC帧
- PPP帧
- 封装成帧是指数据链路层给上层交付下来的协议数据单元PDU添加⼀个首部和⼀个尾部,使之成为帧
- 帧的首部和尾部中包含有一些重要的控制信息
- 帧首部和尾部的作用之一就是帧定界
- 并不是每一种数据链路层协议的顿都包含有帧定界标志
封装成帧,就是将上层传下来的数据加上首部和尾部。通过首部和尾部来指定一个帧的大小。上述中提到
MTU
最大为1500
字节,MTU
同样有最小的限制,最小就是到46
。若MTU
超过1500
就会将其拆分,若没有到达46
,则会在末尾补0
。
# 3.2.2 透明传输
透明传输是指数据链路层对上层交付下来的协议数据单元PDU没有任何限制,就好像数据链路层不存在⼀样。
- 面向字节的物理链路使用字节填充的方法实现透明传输。
- 面向比特的物理链路使用比特填充的方法实现透明传输
透明传输的本质就是当数据传输的过程中都是
01
的格式,通过首部和尾部来区分帧和帧,那么有可能帧的数据载荷中有着和帧首部和尾部相同的01
组合,而透明传输就是为了避免这种情况。避免这种情况的方法十分的简单,类似于C
语言中转义字符。若是面向字节,则填充字节ESC
,而是面向比特,就是通过增加0
破坏和帧首部和尾部相同的结构。如上图给出的可以看到帧的首部和尾部有连续的六个1
,所以在帧的数据载荷中当遇到有五个连续的1
时,就在第5
个1
后面加一个0
。
# 3.2.3 差错检测
FCS
是根据数据部分+首部计算得出的
FCS
就是专门用进行差错检测,在抓包软件中无法看到FCS
,原因是对于FCS
的处理是硬件处理的(也就是路由器),所以当抓包软件抓取时FCS
已经被处理掉了。在数据传输的过程难免会读到数据的错误,而差错检测就是当数据到达时判断这个数据是否错误。较为原始的是奇偶校验,用异或或者与或,这种方法只能检测出现一位错误的情况,出现两位错误就没办法检测出来。而现如今用的比较多的方法是下面说到的CRC
循环冗余校验
# 3.2.4 CRC循环冗余校验
- 数据链路层广泛使用漏检率极低的循环冗余校验(Cyclic Redundancy Check,CRC)检错技术。
- 基本思想
- 收发双方约定好一个生成多项式G(X)
- 发送方基于待发送的数据和生成多项式G(X),计算出差错检测码(冗余码),将冗余码添加到待发送数据的后面一起传输。
- 接收方收到数据和冗余码后,通过生成多项式G(X)来计算收到的数据和几余码是否产生了误码。
所谓的
CRC
循环冗余校验,简单点来说就是在发出的时候根据G(X)
算出余数,这个余数作为冗余码加在数据后面,那么接收方在接收到数据的时候在对数据进行操作,若结果有余数的出现那么就说明传输过程中出现了错误。需要特别注意的中上述中的操作都是异或的操作(相同为
0
,不同为1
)。此外,根据G(X)
算出“除数”就是X
的上标表示的时1
后有多少个0
(或是说在哪个位置上),如图中的 G(x)=x^3^+x^2^+1 也就是1101
。
# 3.3 Ethernet V2标准
- 以太网顿的格式有
Ethernet V2
标准(使用最多)IEEE
的8023
标准
- 为了能够检测正在发送的帧是否产生了冲突,以太网的顿至少要
64
字节 - 用交换机组建的网络,已经支持全双工通信,不需要再使用
CSMA/CD
协议,它传输的帧依然是以太网帧
# 3.3.1 Ethernet V2帧格式
- 格式说明
- 首部:目标
MAC+
源MAC
+ 网络类型 - 以太网帧:首部+数据
+FCS
- 数据的长度至少是:
64-6-6-2-4=46
字节
- 首部:目标
这里需要清楚格式,其中的类型也就是用的是哪种协议,在不同的地方叫法不同,但是核心的意思就是说明这个是什么协议。上图中有一个8字节的内容,目的是为了清楚这一条以太网的MAC帧的长度是多少,方便分别帧与帧。
# 3.3.2 Ethernet V2帧长度标准
- 当数据部分的长度小于
46
字节时- 数据链路层会在数据的后面加入一些字节填充
- 接收端会将添加的字节去掉
- 长度总结
- 以太网帧的数据长度:
46~1500
字节 - 以太网帧的长度
:64~1518
字节
- 以太网帧的数据长度:
# 3.3.3 以太网MAC帧协议
- 接收方可能收到的无效
MAC
帧包括以下几种:MAC
帧的长度不是整数个字节- 通过
MAC
帧的FCS
字段的值检测出顿有误码 MAC
帧的长度不在64~1518
字节之间
- 接收方收到无效的
MAC
帧时,就简单将其丢弃,以太网的数据链路层没有重传机制。
# 3.4 PPP标准
# 3.4.1. PPP概述
- 点对点协议 (Point-to-Point Protocol,PPP)是目前使用最广泛的点对点数据链路层协议
- 点对点协议PPP是因特网工程任务组 (lnternet Engineering Task Force,IETF)于1992年制定的。经过多次修订,目前PPP已成为因特网的正式标准[RFC1661,RFC1662]。
- 点对点协议PPP主要有两种应用:
- 因特网用户
- 广域网路由器链路
# 3.4.2. PPP帧
- 标志(Flag)字段: PPP的定界符,取值为0x7E。
- 地址 (Address)字段: 取值为0xFF,预留 (目前没有什么作用)
- 控制(Control) 字段: 取值为0x03,预留 (目前没有什么作用)
- 协议 (Protocol) 字段: 其值用来指明的数据载荷应向上交付给哪个协议处理
# 第四章 网络层
# 4.1 网际层的设计选择
网络层的主要任务
- 就是将分组从源主机经过多个网络和多段链路传输到目的主机。
- 可以将该任务划分为分组转发和路由选择两种重要的功能。
网络层向上层提供两种服务
- 面向连接的虚电路服务
- 核心思想是“可靠通信应由网络自身来保证
- 通信双方沿着已建立的虚电路发送分组
很多广域分组交换网都使用面向连接的虚电路服务。例如,曾经的X.25
和逐渐过时的帧中继(Frame Relay,FR)、异步传输模式 (Asynchronnous Transfer Mode,ATM)。
- 无连接的数据报服务
- 核心思想是“可靠通信应由用户主机来保证
- 不需要建立网络层连接
- 每个分组可走不同的路径,因此,每个分组的首部都必须携带目的主机的完整地址。
- 通信结束后,没有需要释放的连接
这种通信方式所传送的分组可能误码、丢失、重复和失序。由于网络自身不提供端到端的可靠传输服务,这就使得网络中的路由器可以做得比较简单,大大降低了网络造价。
无连接的数据报服务相对来说较为常用,误码、丢失就不多解释了,重复的原因是有些路线较长,在规定时间没有到达目的地,所有会重新发送数据包,从而造成了重复。失序同理,由于无法预估每个包到达的顺序,所以无法做到有序。
# 4.2 网络层协议
# 4.2.1 IPv4数据报格式
- 在
TCP/IP
标准中,各种数据格式常常以32
比特(即4
字节)为单位来描述。 - 网络层数据包(
IP
数据包,Packet)由首部、数据2
部分组成- 数据:很多时候是由传输层传递下来的数据段(Segment)
# 4.2.2 IPv4数据报首部协议
版本
- (Version)版本
- 长度为
4
个比特,用来表示IP
协议的版本0b0100 : IPv4
0b0110 : IPv6
版本用来表示这个IP协议用的是哪个标准,一般来说都是
IPv4
。
首部长度
- (Header Length)首部长度
- 占4个比特,乘以4才是最终长度,用来表示
IPv4
数据报的首部长度。- 最小取值为二进制的
0101
,20
字节 - 最大取值为二进制的
1111
,60
字节。
- 最小取值为二进制的
首部长度表明了整个
IP
协议首部的大小,最小的为20
个字节,最大为60
个字节,其中20
个字节具体规定了格式,而剩下的40
个字节是自定义可选部分。需要注意的是,可以看到上图中的可变部分存在所谓的填充,这是由于在可选字段中必须以4
个字节一个单位进行增加,若没到要做填充的操作。这个里的4
取决于首部长度每增加1
,那么整个IP
首部的长度都要增加4
。
**可选字段 **
- 长度从
1
字节到40
字节不等,用来支持排错、测量以及安全措施等功能。 - 虽然可选字段增加了
IPv4
数据报的功能,但这同时也使得IPv4
数据报的首部长度成为可变的,这就增加了因特网中每一个路由器处理IPV4
数据报的开销。
填充
- 当首部长度(
20
字节固定部分+可变部分)的长度不是4
字节整数倍时,填充相应数量的全0
字节.以确保IPv4
数据报的首部长度是4
字节的整数倍。 - 使用全
0
进行填充。
区分服务
- (Differentiated Services Field)区分服务
- 占
8
个比特 - 可以用于提高网络的服务质量
- 占
区分服务可以类似的看作与优先级,若一个
IP
首部区分服务中的内容与路由器的设定的内容相匹配,那么路由器就会优先处理这个条数据。
总长度
- (Total Length) 总长度
- 占
16
个比特 - 首部 +数据的长度之和,最大
65535
- 占
总长度用来处理粘包的问题,防止在数据传输过程中路由器分不清包和包。总长度包括了
IPv4
的首部长度加上数据长度。
标识、标志、片偏移
- 由于帧的数据不能超过
1500
字节,所以过大的IP数据包,需要分成片(fragments)传输给数据链路层。- 每一片都有自己的网络层首部(IP首部)
由于
MTU
最大值为1500
个字节,而数据包的到网络层封装完成后最大长度能到达66535
个字节。所以不可避免的就是从网络层到链路层就会出现从大变小的过程也就是拆包。拆包完的小包都要加上一个IP
首部。
标识 (Identification)
- 占
16
比特 - 数据包的
ID
,当数据包过大进行分片时,同一个数据包的所有片的标识都是一样的 - 有一个计数器专门管理数据包的
ID
,每发出一个数据包,ID
就加1
标识可以看作为
ID
,当数据包从网络层传到链路层进行拆包,然后通过路由器进行转发。那么当后面的路由器接收到消息的时传向网络层判断同一个包的方法就是查看小包的标识是否相同。
标记(Flags)
占
3
比特最低位(More Fragment,MF)
MF=1
表示本分片后面还有分片MF=0
表示本分片后面没有分片
中间位(Don't Fragment,DF)
DF=1
表示不允许分片
DF=0
表示允许分片最高位为保留位,必须设置为
0
如上图的情况就是本分片后面没有分片。所以这个包就直接发出就可,不用考虑拆包和拼包的操作。
片偏移(Fragment Offset)
- 占
13
比特 - 片偏移乘以
8
:字节偏移 - 每⼀片的长度⼀定是
8
的整数倍
当我们拆包后,那么我们肯定有拼包的操作吧。那么在拼包的时候就要使用到了片偏移。片偏移记录了数据中的首位对应的是大包中的哪一位。
从
IP
首部的这张图中可以观察到,片偏移相比于字段长度少了三位,那么在计算的时候片偏移要前移三位,也就是所谓的片偏移乘以8
的原因。
生存周期
- 生存时间 (Time To Live,TTL) ,占
8
比特 - 每个路由器在转发之前会将
TTL
减1
,一旦发现TTL
减为0
,路由器会返回错误报告
生命周期可以防止数据在路由器中空转,占用链路空间。
协议
- 长度为
8
个比特,用来指明IPv4
数据报的数据载荷是何种协议数据单元PDU
# 番外( 可以不用关注 )
在述说传输层前先介绍一点应用以及对传输层的朦胧描述,帮助理解传输层。
# Vmware虚拟机网络环境概述
虚拟机------ 软件技术(宿主机里安装一个服务,利用这个服务来共享宿主机的资源,通过服务,虚化成多个独立的主机进行管理)
# 1.Vmware的几种组网方式的区别
- NAT方式
- 宿主机里含有一个
NAT
服务 (网络地址转换器,模拟成路由器)- 宿主机里被安装了一个能够连接到
NAT
路由器的成拟网卡(vmnet8),宿主机就是通过这个网卡和虚拟机通信。 - 虚拟机如果要访问外网,需要配置网关,网关的地址,必须是NAT路由器的
LAN
口IP
(不能是windows
的vmnet8
)。 vmnet8
这个网卡,是给宿主机专门用来访问虚拟机用的,一定不要配置网关和DNS
,这个网卡不是为宿主机提供网络服务假的路由器(软件),外网能不能上,就看宿主机能不能上网了。
- 宿主机里被安装了一个能够连接到
- host-only
- 宿主机里安装了一个虚拟的交换机,为宿主机提供了
vmnet1
的网卡,来连接到交换机上 - 一旦虚拟机网卡连接到
host-only
,就意味连接到了交换机,只能和vmnet1
进行数据交互 - 因为没有路由能力,虚拟机就无法访问外网
- 宿主机里安装了一个虚拟的交换机,为宿主机提供了
- 桥接
- 虚拟机利用宿主机里实际的网卡,充当虚拟机的物理层,虚拟机利用自己的独立
MAC
地址,使用宿主机的物理层进行数据通信 - 寝室里其他设备也可以直接访问到虚拟机
- 虚拟机利用宿主机里实际的网卡,充当虚拟机的物理层,虚拟机利用自己的独立
- 宿主机里含有一个
图中黑线为
NAT
连接方式,蓝色为host-only
连接方式,红色的为桥接方式。平时我们在使用时多数使用的为NAT方式。
# 2.Vmware和windows的数据互通
vmtools无法安装问题
vmtools
就是vmware
这个软件提供的一个插件,只适合同一台机器上宿主机和虚拟机的访问,实验室的多台主机和服务器相连,这个插件无能为力- 建议使用网络服务进行数据交换
C/S模型
client
和server
理解它们可以对比浏览器和百度服务器。
虚拟机里安装ssh的服务器进程
- 如何判断虚拟机里有没有这个服务,若没有就安装
netstat -tuan
查看当前机器的服务 (socket) 链接状态 只需要找本地地址中端口号为22
的,只要有这一行就表示服务已经安装 - 如何安装ssh服务
Ubuntu
: 敲sshd
的命令,自动提示你用什么命令来安装这个服务sudo apt install openssh-server
Centos
: 搜索sshd
的服务是什么软件,然后利用sudo yum instal1 xxxx
每行都表示一条链接 接收缓存 发送缓存本地地址 远程地址 协议 状态
# socket简介
在我们网络分层中,我们用户实际使用的一般只有应用层,而余下的都是由操作系统来完成的。
如果用户要对内核态进行操作要通过文件描述符。文件描述符就是一个非负整数,比如有在Linux
中有如下一张表格
我们需要理解的是先出现的socker
,再出现的网络。所以socket
认为是一张信封,但是socket
是一个大而全的一个通用接口。
# UDP
# UDP服务器编程模型
socket()
获取 操作系统抽象数据结构的对象- 主动的先执行,等待客户端的请求,客户端的请求包到达服务器,如何这个数据包正确的找到服务器的进程
pid
进程号 ---- 端口号- 就是在服务器上,开后门
bind()
系统调用把端口开放
- 等待新的客户端发来请求
recvfrom
# UDP客户端编程模型
socket()
获取 操作系统抽象数据结构的对象bind()
不建议做 该填写自己的端,发送UDP
数据包,src ip:port dest ip:port
- 客户端代码会在不同的机器上运行,无法保证每个客户端都没有使用端口号
- 不调用
bind
,src ip:port
没有信息 - 为了能够将这个数据发送到网卡上,内核就会自动的选择一个当前系统没有被使用的端口号作为
src
sendto()
向某一个IP
和port
上发送数据包
# UDP协议抓包分析
UDP
从协议角度上,只有目的端口、源端口的数据,不提供任何跟有序,无丢失的,传输提供帮助。UDP
面向数据报协议,TCP
面向连接的协议UDP
丢包- 服务器根本就不存在(对应的端口号没有),
UDP
包到了网络层,网络传送给传输层,传输层没有缓存区来存这个数据,自然这个数据就丢失了UDP
的数据包在网终传输中,信号衰减没了
- 服务器根本就不存在(对应的端口号没有),
- 假丢包
- 服务器存在,端口号也正常的,但是由于服务器的执行太慢了,迟迟不能执行到
recvfrom
的接口处此时数据包到达该机器后,分配给UDP
层,UDP
层发现数据包的目的端口和我的一样,把这个数据包暂时存放在缓存区里缓存区里是接收数据包(只要是端口号是这个服务器的,就接收,仓库里按照数据包进行管理的)[TCP
缓存区只能存放一个源地址的信息]
- 服务器存在,端口号也正常的,但是由于服务器的执行太慢了,迟迟不能执行到
UDP
有缓存区,只是这个缓存区里的数据,传输层确认这个数据是否有序,是否丢失,不确定- 丢包:链路和路由选择时,会引起丢失
示例编程
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/types.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]){
struct sockaddr_in self; // 结构体里包含了IP和端口信息
int ret;
ssize_t len;
char buf[256];
int udp_socket = socket(AF_INET,SOCK_DGRAM, 0): // 获取一张信封,传输层采用了UDP技术
// 将这个信封绑定系统的一个端口号,其他客户端就能通过这个端口号向你发出信息
// 服务器就可以通过这个端口号来获取信息了
memset(&self,0,sizeof(self));
self.sin_family = AF_INET;
self.sin_port = htons(7788):
ret = bind(udp_socket, (const struct sockaddr *)&self, sizeof(self));
if (ret == -1) {
perror("bind");
return -1;
}
// 一定要让服务器不能死掉,一般服务器都是循环等待新的客户请求
while (1){
memset(buf, 0, sizeof(buf));
len = recvfrom(udp_socket, buf, sizeof(buf)-1, 0, NULL, NULL);
if(len == -1)
{
perror("recv from");
break;
}
}
close();
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# TCP
TCP
相较于UDP
增加了可靠性传输这一点。TCP
在传输的过程中借助了管道的思想A
发送的数据最终发给B
的内核 (传输层)里的一个队列数据结构,缓存行为,顺序行为。
立用程序阻塞了,不会做任何的代码执行此时客户端向服务器发起链接,这个时候,客户端 能 成功,建立连接的协议,是传输层在做,应用层只是使用者。
UDP
,会丢包,不会粘包TCP
,会发生粘包
示例编程
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/types.h>
#include <arpa/inet.h>
/* TCP 服务器 */
int main() {
struct sockaddr_in self; // 结构体里包含了IP和端口信息
int ret;
// 获取一张信封,传输层采用了TCP技术
int tcp_socket = socket(AF_INET,SOCK_STREAM,0);
if (tcp_socket == -1) {
perror("socket");
return -1;
}
// 将这个信封绑定系统的一个端口号,其他客户端就能通过这个端口号向你发出信息
// TCP服务器就可以通过这个端口号来获取信息 (而是客户端连接的状态) 了
memset(&self,0,sizeof(sef));
self.sin_family = AF_INET;
self.sin_port = htons(6666);
ret = bind(tcp_socket,(const struct sockaddr *)&self, sizeof(self));
if (ret == -1)
{
perror("bind");
return -1;
}
// 默认socket都是具有双向能力,TCP需要一个被动监听的描述符来实现新链接分发 (3次握手)
// 默认的socket的状态,切换成被动监听的状态
listen(tcp_socket,5); // 代表TCP服务器最大有5条链接 (建立3次握手的链接)
char buf[128];
ssize_t len;
// 系统提供了一个叫做accept函数 来接收监听描述符的消息 (3次握手已经成功的消息[新的客户经理])
while (1) {
// 应用层 循环等待新链接
int new_fd = accept(tcp_socket,NULL,NULL):
if (new_fd <0) {
perror("accept");
break;
}
printf("have a new connection!\n");
// 接收客户端发来的消息
len = recv(new_fd,buf,sizeof(buf),0);
if (len <= 0) {
perror("recv"):
break;
}
buf[len] = 0;
printf("client: %s n", buf);
close(new_fd);
}
close(tcp_socket):
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 第五章 传输层
# 5.1 传输层概述
# 5.1.1 传输层的作用
计算机网络体系结构中的物理层、数据链路层和网络层,它们共同解决了将主机通过异构网络互联起来所面临的问题,实现了主机到主机的通信。
如何为运行在不同主机上的应用进程提供直接的逻辑通信服务,就是传输层的主要任务,传输层协议又称为端到端协议。
专输层提供了“端口”的概念,用来区分不同应用进程的标识符。运输层向应用层实体屏蔽了下面网络核心的细节(例如网络拓扑、所采用的路由选择协议等),它使应用进程看见的就好像是在两个运输层实体之间有一条端到端的逻辑通信信道。
根据应用需求的不同,因特网的运输层为应用层提供了两种不同的运输层协议,即面向连接的TCP
和无连接的UDP
,这两种协议就是本章要讨论的主要内容。
传输层可以说是计网整个内容的难点,也是内容十分多的一个点。在传输层中有十分中要的两个协议,一个为
TCP
,一个为UDP
。其中TCP
尤为重要。传输层的作用简单点来说就是以下两点:
- 提供多台主机应用进程之间的端到端的传输行为
- 网络系统识别一个进程,
IP:port
src
dest
- 本机系统识别一个经常,进程号
- 为不可靠的网络层是否提供可靠传输可靠 不可靠
# 5.1.2 TCP/IP运输层中的两个重要协议
TCP
- 传输控制协议 (Transmission Control Protocol,TCP)为其上层提供的是面向连接的可靠的数据传输服务。
- 使用
TCP
通信的双方,在传送数据之前必须首先建立TCP
连接而(逻辑连接,非物理连接)。数据传输结束后必须要释放TCP
连接。 TCP
为了实现可靠传输,就必须使用很多措施,例如TCP
连接管理、确认机制、超时重传、流量控制以及拥塞控制等TCP
的实现复杂,TCP
报文段的首部比较大,占用处理机资源比较多
UDP
- 用户数据报协议 (User Datagram Protocol,UDP)为其上层提供的是无连接的不可靠的数据传输服务。
- 使用
UDP
通信的双方,在传送数据之前不需要建立连接。 UDP
不需要实现可靠传输,因此不需要使用实现可靠传输的各种机制。UDP
的实现简单,UDP
用户数据报的首部比较小。
从上述
TCP
和UDP
的描述可以看出,两个面向的对象不同,TCP
面向的是抽象的链路连接,UDP
面向的是包。TCP
需要确保数据传输的可靠性而UDP
只需要关注把包从自己这边发出去就行了,无需关注这个包是否能被对方收到。由于
TCP
需要可靠传输,所以它的结构十分的复杂,同时也加大了各方的开销。所以现在网络发展的方向是往UDP
进行发展,通过完善下层协议以及加上应用层对于协议的书写,从而让UDP
的传输尽量可靠。
因特网中典型应用使用户的运输层协议
# 5.1.3 传输层端口号
- 运行在计算机上的进程是使用进程标识符 (Process ldentification,PID) 来标识的。
- 然而,因特网上的计算机并不是使用统一的操作系统,而不同操作系统 (Windows、Linux、MacOS) 又使用不同格式的进程标识符。
- 为了使运行不同操作系统的计算机的应用进程之间能够基于网络进行通信,就必须使用统一的
方法对
TCP/IP
体系的应用进程进行标识。
TCP/IP
体系结构的运输层使用端口号来标识和区分应用层的不同应用进程。端口号的长度为16
比特,取值范围是0~65535
。- 端口号的分类
TCP和UDP的端口号之间是没有关系的,他们是独立的。从理论上来说一个进程对应一个端口,但是由于在实际运用过程中为了方便和快捷,可以能会使用多个端口对应一个进程。如上图中
FTP
服务,也就是我们熟知的文件传输服务。它就是申请了两个端口,其实很好理解,文件需要上传和下载,那么自然而然就申请两个端口咯。上述记忆的是HTTP
(80)和HTTPS
(443)。
# 5.1.4 UDP和TCP的对比
# 5.2 UDP报文段格式
UDP
是无连接的,减少了建立和释放连接的开销UDP
尽最大能力交付,不保证可靠交付- 不需要维护复杂的参数,首部只有8个字节 (TCP首部至少20字节)
UDP
长度- 占
16
位,首部的长度+数据长度
- 占
校验和的计算内容:伪首部 +首部 +数据
- 伪首部:仅在计算校验和时起作用,并不会传递给网络层
在
UDP
中的UDP
长度其实完全没有必要,毕竟在网络层的IP
首部中包含了总长度。由于UDP
的长度是固定的8
字节,所以若是我们需要知道数据量有多少只需要将IP
首部中的总长度减去IP
的首部长度,以及UDP
的长度,那么我们就可以算出数据长度。这个UDP
长度更大的作用是用来占位。
UDP
中有检验和,检验和只占两位,它只在数据传输到传输层的时候起效果。在传输层中,会增加一个伪首部,伪首部可以来做校验。
# 5.3 TCP报文段格式
- 序号
- 占
32
比特,取值范围0~2^32^-1当序号增加到最后一个时,下一个序号又回到0
。用来指出本TCP
报文段数据载荷的第一个字节的序号。
- 占
- 确认号
- 占
32
比特,取值范围0~2^32^-1。当确认号增加到最后一个时个确认号又回到0
。用来指出期望收到对方下一个TCP
报文段的数据载荷的第一个字节的序号,同时也是对之前收到的所有数据的确认。
- 占
序号是数据载荷的第一个字节的需要,确认号是希望对方下一个给自己发送的数据的序号。序号的设定存在取模的操作。
以上题为例,我们首先要正确理解主机乙向主机甲要发送的是什么,根据
TCP
的可靠性,题目又告诉我们第2
段没有正确的收到,所以主机乙向主机甲发送的就是第2
段。接着题目告诉我们第
3
段的序号是900
,第2
段的有效载荷是400
,所以第二段的序号为500
,也就是说要发送的确认序列号为500
- 数据偏移
- 占
4
比特,该字段的取值以4
字节为单位。 - 指出
TCP
报文段的数据载荷部分的起始处距离TCP
报文段的起始处有多远,这实际上指出了TCP
报文段的首部长度。
- 占
TCP
中的数据偏移和IP
中偏移量是一个意思,由于只占用4
位,所以要进行乘4
操作。 这也是可选长度中的填充内容的来源。同样数据偏移最小的是20
最大的是60
。
窗口
- 占
16
比特,该字段的取值以字节为单位 - 指出发送本报文段的一方的接收窗口的大小,即接收缓存的可用空间大小,这用来表征接收方的接收能力
- 在计算机网络中,经常用接收方的接收能力的大小来控制发送方的数据发送量.这就是所谓的流量控制。
- 占
校验和
- 占
16
比特 - 用来检查整个
TCP
报文段在传输过程中是否出现了误码
- 占
校验和和
UDP
相同的是也要加上一个首地址。检验是通过异或来完成的,先进行两两异或,并在值存放在检验和的位置,然后当接收方接受时再对数据进行两两异或,在对检验和中的内容进行异或操作,若结果不为零则说明数据出错。计算方法
- 将
TCP
首部中检验和字段的值置为0
- 将伪首部、
TCP
首部以及数据载荷这三部分划分成若干个2
字节的字。若伪首部、TCP
首部以及数据载荷这三部分的总长度不是偶数个字节,则在最后添加1
个“全0
”字节。- 对划分出的全部
2
字节的字进行反码算数运算求和,并将求和结果取反码。- 将步骤3得到的结果写入
TCP
首部中的检验和字段
- 标志位
- 同步标志位
SYN
SYN
为1
的TCP
报文段要么是一个连接请求报文段,要么是一个连接响应报文段
- 终止标志位
FIN
- 用于
TCP
“四报文挥手”释放连接 - 当
FIN=1
时,表明此TCP
报文段的发送方已经将全部数据发送完毕,现在要求释放TCP
连接
- 用于
- 复位标志位
RST
- 用于复位
TCP
连接 - 当
RST=1
时,表明TCP
连接中出现严重差错,必须释放连接,然后再重新建立连接 RST
置1
还用来拒绝一个非法的TCP
报文段或拒绝打开一个TCP
连接。
- 用于复位
- 推送标志位
PSH
- 发送方
TCP
把PSH
置1
,并立即创建一个TCP
报文段发送出去,而不需要积累到足够多的数据再发送。 - 接收方
TCP
收到PSH
为1
的TCP
报文段,就尽快地交付给应用进程,而不再等到接收到足够多的数据才向上交付。
- 发送方
- 同步标志位
- 选项(长度可变,最大
40
字节)- 最大报文段长度
MSS
选项: 指出TCP
报文段数据载荷部分的最大长度,而不是整个TCP
报文段的长度。 - 窗口扩大选项:用来扩大窗口,提高吞吐率。
- 时间戳选项
- 用于计算往返时间
RTT
- 用于处理序号超范围的情况,又称为防止序号绕回
PAWS
- 用于计算往返时间
- 选择确认选项:用来实现选择确认功能
- 最大报文段长度
# 5.4 TCP可靠传输
# 5.4.1 停止等待ARQ协议
- ARQ(Automatic Repeat–reQuest)自动重传请求
- 若有个包重传了
N
次还是失败,会一直持续重传到成功为止吗?- 取决于系统的设置,重传
5
次还未成功就会发送RST
报文,断开连接。
- 取决于系统的设置,重传
其实以上的三种错误情况的解决方法都是超时重传。第一种情况和第二种情况都是发出端长时间没有收到接收端的确认消息,所以进行了超时重传。其实发出端并不关注发生说明什么情况,它只知道长时间没有收到答复要进行重传。
而对于第三种情况,我们在发送数据的时候,
TCP
首部中有序号。假设M1
的序号是1
,数据长度为100
,M2
的序号是200
。那么当发出端进行超时重传M1
,然后发送M2
,此时需要已经到了200
,当接收到确认号为200
的包时就直接抛弃了。
# 5.4.2 连续ARQ协议 + 滑动窗口协议
- 如果接收窗口最多能接
4
个包,但发送方只发了2
个包- 接收方等待一段时间后,没有收到第
3
个包,就会返回确认收到2个包给发送方
- 接收方等待一段时间后,没有收到第
- 每个包多大那,每个确认编号如何编址
- 序号和确认号
这里的滑动窗口和平时刷题中的滑动窗口其实就是一个东西。当然这个滑动窗口的大小可以在应用层上自主定义。比方说这里发送
4
个包的数据,那么接收方返回的值为发生错误的序列号或者是最后一个包的后一个序列号。当然,当我们下一次发送时已经发送的包就不用再次发送了。
# 5.4.3 选择性确认(SACK)
在TCP通信过程中,如果发送序列中间某个数据包丢失 (比如1、2、3、4、5
中的3
丢失了),TCP
会通过重传最后确认的分组后续的分组(最后确认的是2
,会重传3、4、5
),这样原先已经正确传输的分组也可能重复发送 (比如4、5
) ,降低了TCP
性能。
- 发展出了
SACK
(Selective acknowledgment,选择性确认) 技术- 告诉发送方哪些数据丢失,哪些数据已经提前收到
- 使
TCP
只重新发送丢失的包 (比如3
) ,不用发送后续所有的分组 (比如4、5
)
SACK
信息会放在TCP
首部的选项部分Kind
:占1
字节。值为5
代表这是SACK
选项Length
: 占1
字节。表明SACK
选项一共占用多少字节Left Edge
:占4
字节,左边界Right Edge
:占4
字节,右边界
所谓的选择性确定简单的来说就是为了提高发送端的效率,不需要重传所有数据段,只需要重传 接收端没有收到的段。就像是上一章中不传数据段
8
。第一幅图是在TCP
头部中的选项部分的内容。这边的边界是左闭右开的。如同第二幅图一样,第一块没有接收到,那么接收方发给发出方的边界就为[201,301)。
- 一对边界信息需要占用
8
字节,由于TCP
首部的选项部分最多40
字节SACK
选项最多携带4
组边界信息SACK
选项的最大占用字节数 =4*8+2=34
图中画框的就是一趟完整的发送方多段发送,接收方返回一段数据的过程。
为什么选择在传输层将数据分成多个段,而不是等到网络层分片传递给数据链路层。
这个问题可以用
ping
命令来解释。接受方接受到ping
命令的时候其实根本不会送到传输层。若ping
一个很大的数据包,那么在发送的时候网络层就要对数据进行一个拆包处理。在平时的网络通信中用到最多的就是TCP
协议,但网络协议不仅仅只有TCP
协议,就如同ping
命令用的是ICMP
协议。
# 5.5 TCP流量控制
应用程序可能正忙于其他任务,并不一定能够立刻取走数据。客户端持续发送大量数据,接收端缓存会溢出,造成数据丢失
TCP
为应用程序提供了流量控制 (Flow Control) 机制,以解决因发送方发送数据太快而导致接收方来不及接收,造成接收方的接收缓存溢出的问题。
# 5.5.1 基本情况
- 流量控制的基本方法: 接收方根据自己的接收能力 (接收缓存的可用空间大小)控制发送方的发送速率
- 通过确认报文中窗口字段来控制发送方的发送速率
- 发送方的发送窗口大小不能超过接收方给出窗口大小
- 当发送方收到接收窗口的大小为
0
时,发送方就会停止发送数据
一般来说接收端的数据处理数据相较于发送端的
I/O
速度会慢上很多,那么接收端就会对发出端的滑动窗口大小进行一定的限制,这样就可以定量的控制发送端发出的数据段,从而做到流量控制。
# 5.5.2 特殊情况
一开始,接收方给发送方发送了0
窗口的报文段,后面,接收方又有了一些存储空间,给发送方发送的非0
窗口的报文段丢失了,发送方的发送窗口一直为零,双方陷入僵局。
- 解决方案
- 当发送方收到
0
窗口通知时,这时发送方停止发送报文 - 并且同时开启一个定时器,隔一段时间就发个测试报文去询问接收方最新的窗口大小
- 如果接收的窗口大小还是为
0
,则发送方再次刷新启动定时器
- 当发送方收到
其实特殊情况的处理方法说到底就是超时重传。当发出端没有收到接收端发来的确认的消息,那就会启动一个计时器,没过一段时间就发一段数据,询问接收端是否要发送数据,直到
TCP
连接断开。
# 5.6 TCP拥塞控制
# 5.6.1 什么是拥塞控制
拥塞:在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络性能就要变坏,这种情况就叫作拥塞 (congestion)。
- 计算机网络中的链路容量(带宽)、交换节点中的缓存和处理机等都是网络的资源
拥塞控制是一个全局性的过程
- 涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素
- 是需要靠所有节点共同努力的结果
- 防止过多的数据注入到网络中,使网络能够承受现有的网络负荷
相比而言,流量控制是点对点通信的控制
从图中的线型图中可以看出,实际情况的拥塞情况和理论上的情况并不相同。只要是因为在数据传输的过程中有很多的因素会影响传输效率。如处理时延、分组传输等。
# 5.6.2 拥塞控制的常用算法
方法概述
- 慢开始 (slow start,慢启动)
- 拥塞避免 (congestion avoidance)
- 快速重传 (fast retransmit)
- 快速恢复 (fast recovery)
几个缩写
cwnd
(congestion window) : 拥塞窗口rwnd
(receive window) : 接收窗口swnd
(send window) : 发送窗口,swnd = min(cwnd,rwnd)
慢开始
cwnd
的初始值比较小,然后随着数据包被接收方确认 (收到一个ACK
)- cwnd成倍增长(指数级)
从前面的学习来看,这张图中有点错误,实际上只会返回一个确认包。
拥塞避免
ssthresh
(slow start threshold) : 慢开始值,cwnd
达到闯值后,以线性方式增加- 拥塞避免 (加法增大):拥塞窗口缓慢增大,以防止网络过早出现拥塞
- 乘法减小:只要网络出现拥塞,把
ssthresh
减为拥塞峰值的一半,同时执行慢开始算法 (cwnd
又恢复到初始值) - 当网络出现频繁拥塞时,
ssthresh
值就下降的很快
慢开始和拥塞避免要放在一起看。就如同上图中阐述的内容一样。先是通过慢开始启动,到达
ssthresh
这一阈值,在这阈值之前是指数级增长,而超过了阈值就是线性增长。这是为了防止增长太快直接导致拥塞,减缓传输的效率。当线性增长到网络拥塞的点后,拥塞窗口会迅速缩小到一开始设定的大小,重新进行慢开始,慢开始的ssthreash
将会变为发生网络拥塞值时的一半(这里注意不是原来慢开始的一半)。
快重传
接收方
- 每收到一个失序的分组后就立即发出重复确认
- 使发送方及时知道有分组没有到达
- 而不要等待自己发送数据时才进行确认
发送方
- 只要连续收到三个重复确认 (总共
4
个相同的确认),就应当立即重传对方尚未收到的报文段 - 而不必继续等待重传计时器到期后再重传
- 只要连续收到三个重复确认 (总共
对于个别丢失的报文段,发送方不会出现超时重传,也就不会误认为出现了拥塞而错误地把拥塞窗口cwnd
的值减为1
。实践证明,使用快重传可以使整个网络的吞吐量提高约20%
。
上图中可以看出是一下子传了
M1~M6
,在返回确认的时候通过返回三个确认M2
,那么发送方就会立马重传M3
,由于接收方其实已经接受到了M4~M6
,所以不用发这些包。这个和之前说的SACK
其实是一个东西。同时需要明白对于这边的3
个连续的对M2
的重复确认,并没有判定发生拥塞,仅仅是因为段的丢失。
快恢复
- 当发送方连续收到三个重复确认,说明网络出现拥塞
- 就执行“乘法减小”算法,把
ssthresh
减为拥塞峰值的一半
- 就执行“乘法减小”算法,把
- 与慢开始不同之处是现在不执行慢开始算法,即
cwnd
现在不恢复到初始值- 而是把
cwnd
值设置为新的ssthresh
值 (减小后的值) - 然后开始执行拥塞避免算法 (“加法增大”),使拥塞窗口缓慢地线性增大
- 而是把
快恢复就是将拥塞后,拥塞窗口缩小到拥塞时的一半大小,直接跳过慢开始的过程。
# 5.7 TCP建立连接和释放连接
# 5.7.1 三次握手
第一次握手
- 看到
SYN=1
,就是说明这次的请求是建立连接。第一次握手是平时在做题中唯一的一种ACK=0
的情况,其他时候ACK=0
。这里比较奇特的是seq
(序号)是x
值,原因是当发送数据的时候会生成一个随机值,这个随机值是双方约定的,这个做法是为了增加安全性。(下图中可以看到Seq
的理论值为0
,但是实际值为2850249425
)而且这个x
值是在实际的发送数据的前一位,也就是TCP
服务器接受窗口的前一位,这个包是不带任何数据的。看上图中的第一条数据的Len
的值为0
就可以说明这点了。
第二次握手
第二次握手的
ack
(确认号)自然就是上次握手传入的seq
值+1
咯,也就是x+1
。由于数据传输的双方相互的行为,所以服务端自然也要返回一个seq
,这个seq
和客户端发送的seq
没有任何关系,但是也进行了加密处理。第三次握手
第三次握手发送的
seq
的值为x+1
,显然这是为了回复第二次握手中传进来的ack
。但是这个seq
比较特殊,因为讲道理来说x+1
存放的实际是我们将要发送数据的首字节的位置。但是我们在实际传输的过程中是不传数据的,就像是一开始的图中可以看到第三条数据的Len
也为0
。
为什么必须是三次握手而不是二次握手
采用“三报文握手”而不是“两报文握手”来建立TCP
连接,是为了防止已失效的TCP
连接请求报文段突然又传送到了TCP
服务器进程,因而导致错误。
为了理解上面这句话,下面列举一个例子。
![]()
就像是上面这个图中所展示的内容,客户端发送请求,但是由于网络过慢的等原因,导致这个请求到达服务端的速度过慢,所以客户端要进行超时重传,如果只进行二次握手(那么双方进行收发文件确实可以),但是当客户端关闭后,之前那个因为网络比较慢的亲求到达服务端,那么理应服务端会返回一个确认请求,而此时客户端都已经关闭了,自然也不会发送确认请求给服务端,那么服务端就会一直进行超时重传。这样就会一直占用服务端,资源无法正常释放。
# 5.7.2四次挥手
第一次挥手
- 序号
seq
字段的值设置为u
,它等于TCP
客户进程之前已经传送过的数据的最后一个字节的序号加1
。 TCP
规定终止标志位FIN
等于1
的TCP
报文段即使不携带数据,也要消耗掉一个序号。- 确认号
ack
字段的值设置为v
,它等于TCP
客户进程之前已收到的数据的最后一个字节的序号加1
.
- 序号
第二次挥手
- 序号
seq
字段的值设置为v
,它等于TCP
服务器进程之前已传送过的数据的最后一个字节的序号加1
。这也与之前收到的TCP
连接释放报文段中的确认号v
匹配 - 确认号
ack
字段的值设置为u+1
,这是对TCP
连接释放报文段的确认。
- 序号
经过两次挥手后,从TCP
客户进程到TCP
服务器进程这个方向的连接就释放了,但TCP
服务器进程如果还有数据要发送,TCP
客户进程仍要接收,也就是从TCP
服务器进程到TCP
客户进程这个方向的连接并未关闭。
- 第三次挥手
TCP
连接释放报文段首部中的终止标志位FIN和确认标志位ACK
的值都被设置为1
。表明这是一个TCP
连接释放报文段,同时也对之前收到的TCP
报文段进行确认。- 序号
seq
字段的值假定被设置为w
,这是因为在半关闭状态下TCP
服务器进程可能又发送了一些数据。 - 确认号
ack
字段的值被设置为u+1
,这是对之前收到的TCP
连接释放报文段的重复确认。 - TCP服务器进入
LAST-ACK
状态
- 第四次挥手
- 序号
seq
字段的值设置为u+1
,这是因为TCP
客户进程之前发送的TCP
连接释放报文段虽然不携带数据,但要消耗掉一个序号。 - 确认号
ack
字段的值设置为w+1
,这是对所收到的TCP
连接释放报文段的确认。 TCP
客户端进入TIME-WAIT
状态,等待2MLS
,MSL
是最长报文段寿命 (Maximum SegmentLifetime)的英文缩写词,[RFC793]
建议为2
分钟。也就是说,TCP
客户进程进入时间等待(TIME-WAIT) 状态后,还要经过4
分钟才能进入关闭 (CLOSED) 状态。
- 序号
四次挥手考研不是很关注。有两个问题可能会被问到。
- 存在大量的关闭等待,原因是服务器网速比较慢,第三次挥手的发送慢。
- 存在大量的时间等待,这种情况就是正常情况,不用理会。
# 第六章 应用层之HTTP
# 6.1 应用层概念
应用层是计算机网络体系结构的最顶层,是设计和建立计算机网络的最终目的,也是计算机网络中发展最快的部分。包括:
早期基于文本的应用 (电子邮件、远程登录、文件传输、新闻组),20
世纪90
年代将因特网带入家万户的万维网WWW
,当今流行的即时通信、P2P
文件共享及各种音视频应用。
应用层协议的定义
应用层协议(application layer protocol) 定义了在不同端系统上应用程序是如何相互传输报文的。一般来说,应用层协议会规定如下内容:
- 交换的报文类型:交换的是请求报文还是响应报文
- 报文字段的解释:对报文中各个字段的详细描述
- 报文字段的语义:报文各个字段的含义是什么
- 报文交换时间、方式:程序何时、以什么方式发送报文以及响应
直白一点来说,应用层只是产生和使用数据的逻辑层,在这一层次我们并不会关心它们是如何发送数据的以及数据发到哪里。应用层有两种层次结构。
# 6.2 应用层体系结构
应用层体系结构(Application Architecture)定义了应用层端系统之间数据交换的方式,开发一种新的网络应用,首先要考虑的问题就是网络应用程序在各种端系统上的组织方式和它们之间的关系一般来说,主流的体系结构有两种:
- 客户-服务器体系结构(client-server architecture)
- 对等体系结构(P2P architecture)
# 6.2.1 客户/服务器方式
在客户-服务器体系结构中,分为请求方和服务方。有一个总是打开的主机称为服务端(Server),向客户端(client)提供服务。客户端会发送请求给服务端,服务端会根据客户端的请求做出响应。
体系特点
- 客户和服务器是指通信中所涉及的两个应用进程
- 客户/服务器方式所描述的是进程之间服务和被服务的关系。
- 客户是服务请求方,服务器是服务提供方。
- 服务器总是处于运行状态,并等待客户的服务请求
我们最常见的服务端就是Web
服务器,Web
服务器提供于来自浏览器的请求。我们日常访问百度、谷歌,其实就是在访问它们的Web
服务器。
一般常见的 Web
服务器主要有Apache
、IIS
、Jboss
、Tomcat
、WebSphere
、WebLogic
等。
当Web
服务器通过浏览器接收到用户请求后,它会经过一系列的处理把信息或者页面等通过浏览器呈现给用户。这种模式就是客户-服务器模式。
这里有两点需要注意:
- 在客户 - 服务器模式下,通常客户彼此之间是并不互相通信的。
- 服务器通常具有固定的、周知的
IP
地址可以提供访问。比如我们平时使用
C/S
方式通常会出现随着客户数量的急剧增加导致单台服务器无法满足大量请求的情况。为此,通常需要配备大量的数据中心(data center),用来跟踪所有的用户请求,这里就产生了大量的经济成本的消耗。
# 6.2.2 点对点方式
在P2P
方式中,没有固定的服务请求者和服务提供者,分布在网络边缘各端系统中的应用进程是对等的,被称为对等方。对等方相互之间直接通信,每个对等方既是服务的请求者,又是服务的提供者。
在因特网上流行的P2P
应用主要包括P2P
文件共享、即时通信、P2P
流媒体、分布式存储等
P2P
一个最大的特点就是扩展性(self-scalability),因为 P2P
网络的一个重要的目标就是让所有的客户端都能提供资源、获取资源,共享带宽,存储空间等。因此,当有更多节点加入且对系统请求增多,整个系统的容量也增大。这是具有一组固定服务器的客户 - 服务器结构不具备的,这也就是 P2P
的 优势。P2P
方式具有成本上的优势,因为它通常不需要庞大的服务器设置和服务器带宽。为了降低成本,服务提供商对于将P2P
方式用于应用的兴趣越来越大。
这个点对点在视频传输中用到的很多。由于视频一般都很大,所以要是使用
C/S
那么对带宽的要求就很大。所以就使用P2P
模式。比如,看电影。A
在看电影,然后E
看同一部电影,那么A
就会成为服务器,接着E
就能看到了,这样就平坦了网线压力。
# 6.3 万维网
# 6.3.1 万维网概述
万维网 (World Wide Web,WWW) 并非某种特殊的计算机网络。它是一个大规模的、联机式的信息储藏所,是运行在因特网上的一个分布式应用。万维网利用网页之间的超链接将不同网站的网页链接成一张逻辑上的信息网。
万维网(www,World Wide Web)是将互联网中的信息以超文本的形式展现的系统,用来显示WWW结果的客户端被称为 Web 浏览器。通过浏览器,我们无需关注想要访问的内容在哪个服务器上我们只需要知道我们想访问的内容就可以了。

WWW 定义了三个比较重要的概念,这些概念主要有
- URI定义了访问信息的手段和位置
- 文档规范
HTTP
定义了www
的访问规范
# 6.3.2 统⼀资源定位符
URI
(Uniform Resource ldentifier)中文名称是统一资源标识符,使用它就能够唯一地标记互联网上资源。
URL
(Uniform Resource Locator)中文名称是统一资源定位符,也就是我们俗称的网址,它实际上是URI
的一个子集。
URI
不仅包括URL
,还包括URN
(统一资源名称) ,它们之间的关系如下:

URI
已经不局限于标识互联网资源,它可以作为所有资源的识别码。URL
的一般形式由以下四个部分组成:
https://moyangsun.github.io/blogs/category1/2024/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.html
比如上述的网址是我的博客中数据结构的网址
协议:https
主机:moyangsun.github.io(端口是https协议的默认值端口443)
路径:/blogs/category1/2024/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.html
# 6.3.3 万维网文档
HTML
超文本标记语言(HyperText Markup Language,HTML),使用多种“标签”来描述网页的结构和内容。HTML
称为超文本标记语言,是一种标识性的语言。它包括一系列标签,通过这些标签可以将网络上的文档格式统一,使分散的lnternet
资源连接为一个逻辑整体。HTML
文本是由HTML
命令组成的描述性文本,HTML
命令可以说明文字,图形、动画、声音、表格、链接等
CSS
层叠样式表(Cascading Style Sheets,CSS),从审美的角度来描述网页的样式
JavaScript
⼀种脚本语⾔,控制网页的行为。
HTTP
Web
的应用层协议就是HTTP
(HyperText Transfer Protocol,HTTP),超文本传输协议,它是Web
的核心协议。下面是 HTTP 协议中的几个核心概念
HTTP
定义了浏览器(即万维网客户进程)怎样向万维网服务器请求万维网文档,以及万维网服务器怎样把万维网文档传送给浏览器。
# 6.4 HTTP
HTTP
是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。HTTP
是一种应用层协议,它使用TCP
作为运输层协议,因为文档、数据这些信息在我们看来是种重要的信息,不可丢失。
# 6.4.1 HTTP连接行为
HTTP/1.0
HTTP/1.0
采用非持续连接方式。在该方式下,每次浏览器要请求一个文件都要与服务器建立TCP
连接,当收到响应后就立即关闭连接。
每请求一个文档就要有两倍的RTT
的开销。若一个网页上有很多引用对象(例如图片等),那么请求每一个对象都需要花费2RTT
的时间。
为了减小时延,浏览器通常会建立多个并行的TCP
连接同时请求多个对象。但是,这会大量占用万维网服务器的资源,特别是万维网服务器往往要同时服务于大量客户的请求,这会使其负担很重。
这里要清楚两点
- 三次握手的第三次,从协议上来说就只会发送一个
ACK
包(确认包),但是这样一来就浪费了一轮传输数据。所以在平时的网络中常常会在第三次握手加上数据,也就是上述图中的HTTP
请求报文,从而来增加效率HTTP/1.0
,采用简单除暴的每次连接就只处理一个请求,这样虽然便于应用层的书写,但是会占用服务器的大量资源。若采用HTTP/1.0
模式,一般的连接方式都是Connection: close
HTTP/1.1
HTTP/1.1
采用持续连接方式。在该方式下,万维网服务器在发送响应后仍然保持这条连接,使同一个客户(浏览器)和该服务器可以继续在这条连接上传送后续的HTTP请求报文和响应报文。这并不局限于传送同一个页面上引用的对象,而是只要这些文档都在同一个服务器上就行
为了进一步提高效率,HTTP/1.1
的持续连接还可以使用流水线方式工作,即浏览器在收到HTTP
的响应报文之前就能够连续发送多个请求报文。这样的一个接一个的请求报文到达服务器后,服条器就发回一个接一个的响应报文。这样就节省了很多个RTT
时间,使TCP
连接中的空闲时间减少,提高了下载文档的效率。
HTTP/1.1
相较于HTTP/1.0
有两点主要的不同
- 改变了连接的方式,从
close
改变到了keep-alive
。这样的改动,能长时间让客户端和服务器连接- 流水线方式工作可以在收到
HTTP
的响应报文之前就能够连续发送多个请求报文。
# 6.4.2 HTTP报文格式
HTTP 协议主要由三大部分组成:
- 起始行 (start line):描述请求或响应的基本信息。
- 头部字段 (header) :使用
key-value
形式更详细地说明报文。 - 消息正文 (entity) :实际传输的数据,它不一定是纯文本,可以是图片、视频等二进制数据。
其中起始行和头部字段并称为请求头或者响应头,统称为 Header
; 消息正文也叫做实体,称为body
。HTTP
协议规定每次发送的报文必须要有 Header
,但是可以没有 body
,也就是说头信息是必须的,实体信息可以没有。而且在 header
和 body
之间必须要有一个空行 (CRLF)。如果用一幅图来表示一下HTTP
请求的话,我觉得应该是下面这样:

HTTP请求
这幅图需要注意一下,如果使用 GET
方法,是没有实体体的,如果你使用的是 POST
方法,才会有实体体。当用户提交表单时,HTTP
客户端通常使用 POST
方法;与此相反,HTML
表单的获取通常使用GET
方法。HEAD
方法类似于GET
方法,只不过HEAD
方法不会返回对象。


需要注意的是,这里的
HTTP
报文的格式有十分严格的规定,一旦出错就会出现接收错误。上图中的空格和换行都是用特殊的字符来代替(换行也就是C
语言中的\r\n
,也就是图中的CRLF
)如下图中的第一行就是请求行,剩下的是首部行
HTTP响应


上图中的
1、2、3
,要是这三种状态一般来说就是连接没有什么问题。特别说明3XX
这种情况,比如用户保存了一个网站目录,后来服务器对网站目录进行了更改,那么为了让用户继续能访问到会有一个重定向行为。还如我的blog
,其实我是将资源全部都放在github
上面,但是github
提供了一个重定向的功能来帮助网页的渲染。
# 6.4.3 HTTP协议特征
从上面整个过程中我们可以总结出 HTTP 进行分组传输是具有以下特征
支持客户-服务器模式
简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有
GETHEAD
、POST
。每种方法规定了客户与服务器联系的类型不同。由于HTTP
协议简单,使得HTTP
服务器的程序规模小,因而通信速度很快。灵活:
HTTP
允许传输任意类型的数据对象。正在传输的类型由Content-Type
加以标记无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
无状态:
HTTP
协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
# 6.4.4 cookie和session
HTTP
协议是一种无状态协议,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录;Session
和 Cookie
的主要目的就是为了弥补 HTTP
的无状态特性。
cookies是什么
HTTP
协议中的 Cookie
包括 Web Cookie
和浏览器 Cookie
,它是服务器发送到 Web
浏览器的小块数据。服务器发送到浏览器的 Cookie
,浏览器会进行存储,并与下一个请求一起发送到服务器。通常,它用于判断两个请求是否来自于同一个浏览器,例如用户保持登录状态。
HTTP Cookie
机制是HTTP
协议⽆状态的⼀种补充和改良
Cookie 主要⽤于下⾯三个目的:
- 会话管理
- 登陆、购物车、游戏得分或者服务器应该记住的其他内容
- 个性化
- 用户偏好、主题或者其他设置
- 追踪
- 记录和分析用户行为
Cookie
曾经用于一般的客户端存储。虽然这是合法的,因为它们是在客户端上存储数据的唯一方法,但如今建议使用现代存储 API
。 Cookie
随每个请求一起发送,因此它们可能会降低性能(尤其是对于移动数据连接而言)
cookies的过程
当接收到客户端发出的 HTTP
请求时,服务器可以发送带有响应的 Set-Cookie
标头, Cookie
通常由浏览器存储,然后将 Cookie
与 HTTP
标头一同向服务器发出请求。
Set-Cookie 和 Cookie 标头:
Set-Cookie HTTP 响应标头将 cookie 从服务器发送到用户代理
此标头告诉客户端存储 Cookie
。
现在,随着对服务器的每个新请求,浏览器将使用 Cookie
头将所有以前存储的 Cookie
发送回服务器。
有两种类型的 Cookies
,一种是 Session Cookies
,一种是 Persistent Cookies
,如果 Cookie
不包含到期日期,则将其视为会话 Cookie
。会话 Cookie
存储在内存中,永远不会写入磁盘,当浏览器关闭时,此后 Cookie
将永久丢失。如果 Cookie
包含有效期,则将其视为持久性 Cookie
。在到期指定的日期,Cookie
将从磁盘中删除。
上面的示例创建的是会话 Cookie
,会话 Cookie
有个特征,客户端关闭时 Cookie
会删除,因为它没有指定Expires
或Max-Age
指令。
但是,Web
浏览器可能会使用会话还原,这会使大多数会话 Cookie
保持永久状态,就像从未关闭过浏览器一样。
HTTP
协议是一种无状态协议,所以为了确保服务器能认识客户端,所以就引出了Cookies
技术。这种技术简单点说就是当客户端首次向服务器发消息,服务器生成能够识别客户端的信息并返回给客户端,客户端(浏览器)以后只要访问你的网站,就会自动携带这个Cookie
信息通过请求数据发给服务器。
永久性 Cookies
永久性 Cookie 不会在客户端关闭时过期,而是在特定日期(Expires)或特定时间长度(Max-Age )外过期。例如:
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2023 07:28:00 GMT;
永久性也就是把时间设置的长一点。
Cookies
的非常好用,但是也充满了争议,由于数据是在客户端保留的,这样就会造成安全性问题。比如当我们在外面登入过某些网站,那么Cookies
就会保存在浏览器上,如果我们没有对Cookies
进行清楚就会引发安全问题。还是就是说数据存储在本地,那么就可以修改数据。比如本来登入一个网站,你的账号是vip1
,那么修改Cookies
就可以把vip
等级进行修改,对网站的利益造成了损害。
session
客户端请求服务端,服务端会为这次请求开辟一块内存空间,这个对象便是 Session
对象,存储结构是一个 Map
映射,具体一点是 ConcurrentHashMap
。Session
弥补了 HTTP
无状态特性,服务器可以利用 Session
存储客户端在同一个会话期间的一些操作记录。
session如何判断是否是同一会话
服务器第一次接收到请求时,开辟了一块
Session
空间 (创建了Session
对象),同时生成一个sessionld
,并通过响应头的Set-Cookie: JSESSIONID=XXXXXXX
命令,向客户端发送要求设置Cookie
的响应; 客户端收到响应后,在本机客户端设置了一个JSESSIONID=XXXXXXX
的Cookie
信息,该Cookie
的过期时间为浏览器会话结束;
接下来客户端每次向同一个网站发送请求时,请求头都会带上该 Cookie
信息(包含 sessionld
),然后服务器通过读取请求头中的 Cookie
信息,获取名称为 JSESSIONID
的值,得到此次请求的sessionld
.
session
机制有个缺点,比如 A
服务器存储了 session
,就是做了负载均衡后,假如一段时间内 A
的访问量激增,会转发到 B
进行访问,但是 B 服务器并没有存储 A
的 session
,会导致 session
的失效。
![]()
session
服务器提供仓库,专门保存每一个客户链接所需要的数据(身份信息,身份状态)。这种一般平时使用内存数据库,比较常用的是使用redis
。客户端通过服务器给自己的Set-Cookies
进行访问,由于数据不在本地,所以用户就没有权限进行更改。
# 第七章 应用层之DNS和DHCP
# 7.1 DNS协议
# 7.1.1 DNS系统概述
试想一个问题,我们人类可以有多少种识别自己的方式? 可以通过身份证来识别,可以通过社保卡号来识别,也可以通过驾驶证来识别,尽管有多种识别方式,但在特定的环境下,某种识别方法会比其他方法更为适合。因特网上的主机和人类一样,可以使用多种方式进行标识。互联网上主机的一种标识方法是使用它的主机名(hostname),比如 www.baidu.com
、www.google.com
等。这是我们人类习惯的记忆方式,因特网中的主机却不会这么记忆,它们喜欢定长的、有层次结构的 IP 地址
DNS
的全称是 Domain Name System
,DNS
,它是一个由分层的 DNS
服务器 (DNS server) 实现的分布式数据库;它还是一个使得主机能够查询分布式数据库的应用层协议。DNS
服务器通常是运行BIND
(Berkeley Internet Name Domain) 软件的 UNIX
机器。DNS
协议可以运行在 UDP
之上,也可以运行在 TCP
之上,使用 53
端口。
DNS
通常不是一门独立的协议,它通常为其他应用层协议所使用,这些协议包括 HTTP
、SMTP
和FTP
,将用户提供的主机名解析为IP
地址。
DNS就可以简单的理解为给一个网站取了一个别名。比如
www.baidu.com
,我们可以直接拼这个网址,但是这个域名其实在背后对应了一个IP
地址。
# 7.1.2 DNS系统结构
- 因特网是否可以只使用一台DNS服务器?
- 这种做法并不可取。因为因特网的规模很大,这样的域名服务器肯定会因为超负荷而无法正常工作,而且一旦域名服务器出现故障,整个因特网就会瘫痪。
- 早在
1983
年,因特网就开始采用层次结构的命名树作为主机的名字(即域名),并使用分布式的域名系统DNS
。 DNS
使大多数域名都在本地解析,仅少量解析需要在因特网上通信,因此系统效率很高- 由于
DNS
是分布式系统,即使单个计算机出了故障,也不会妨碍整个系统的正常运行。
DNS
最早的设计是只有一台DNS
服务器。这台服务器会包含所有的DNS
映射这是一种集中式的设计,这种设计并不适用于当今的互联网,因为互联网有着数量巨大并且持续增长的主机,这种集中式的设计会存在以下几个问题:- 单点故障(a single point of failure),如果 DNS 服务器崩溃,那么整个网络随之瘫痪
- 通信容量(traaffic volume),单个 DNS 服务器不得不处理所有的 DNS 查询,这种查询级别能是上百万上千万级。
- 远距离集中式数据库(distant centralized database),单个 DNS 服务器不可能 近 所有的用户,假设在美国的 DNS 服务器不可能临近让澳大利亚的查询使用,其中查询请求势必会经过低速和拥堵的链路,造成严重的时延。
- 维护(maintenance),维护成本巨大,而且还需要频繁更新。
# 7.1.3 域名结构
- 因特网采用层次树状结构的域名结构。
- 域名的结构由若干个分量组成,各分量之间用“点”隔开,分别代表不同级别的域名。
- 每一级的域名都由英文字母和数字组成,不超过
63
个字符,不区分大小写字母 - 级别最低的域名写在最左边,而级别最高的顶级域名写在最右边。
- 完整的域名不超过255个字符。
- 每一级的域名都由英文字母和数字组成,不超过
http://mirrors.ustc.edu.cn/help/ubuntu.html
- 域名系统既不规定一个域名需要包含多少个下级域名,也不规定每一级的域名代表什么意思。
- 各级域名由其上一级的域名管理机构管理,而最高的顶级域名则由因特网名称与数字地址分配机构
ICANN
进行管理。 - 顶级域名(Top Level Domain,TLD)分为以下三类
- 国家顶级域名
nTLD
- 采用
ISO 3166
的规定。如cn
表示中国,us
表示美国,uk
表示英国、等等
- 采用
- 通⽤顶级域名
gTLD
- 最常见的通用顶级域名有七个,即:
com
(公司企业)、net
(网络服务机构)、org
(非营利性组织)、int
(国际组织)、edu
(美国教育机构) 、gov
(美国政府部门) 、mil
(美国军事部门)。
- 最常见的通用顶级域名有七个,即:
- 反向域
arpa
- 用于反向域名解析,即
IP
地址反向解析为域名。
- 用于反向域名解析,即
- 国家顶级域名
- 在国家顶级域名下注册的二级域名均由该国家自行确定。例如,顶级域名为jp的日本,将其教育和企业机构的二级域名定为
ac
和co
,而不用edu
和com
。 - 我国则将二级域名划分为以下两类:
- 类别域名
- 共七个:
ac
(科研机构) 、com
(工、商、金融等企业) 、edu
(教育机构)、gov
(政府部门)、net
(提供网络服务的机构) 、mil
(军事机构)和org
(非营利性组织)
- 共七个:
- 行政区域名
- 共34个,适用于我国的各省、自治区、直辖市。例如:
bj
为北京市、sh
为上海市、js
为江苏省,等等。
- 共34个,适用于我国的各省、自治区、直辖市。例如:
- 类别域名
这种按等级管理的命名方法便于维护名字的唯一性,并且也容易设计出一种高效的域名查询机制。需要注意的是,域名只是个逻辑概念,并不代表计算机所在的物理地点。
# 7.1.4 域名服务器
域名和IP
地址的映射关系必须保存在域名服务器中,供所有其他应用查询。显然不能将所有信息都储存在一台域名服务器中。DNS使用分布在各地的域名服务器来实现域名到IP
地址的转换。
大致来说有三种 DNS
服务器: 根 DNS
服务器、顶级域(Top-Level Domain, TLD) DNS
服务器和 权威 DNS
服务器 。这些服务器的层次模型如下图所示:
假设现在一个 DNS
客户端想要知道 www.amazon.com
的 IP
地址,那么上面的域名服务器是如何解析的呢?
首先,客户端会先和根服务器之一进行关联,它将返回顶级域名 com
的 TLD
服务器的 IP
地址。该客户则与这些 TLD
服务器之一联系,它将为 amazon.com
返回权威服务器的 IP
地址。最后,该客户与amazom.com
权威服务器之一联系,它为 www.amazom.com
返回其IP
地址。
# 7.1.5 DNS查询步骤

整个流程如下图所示

- 用户在浏览器中输入网址
www.example.com
并点击回车后,查询会进入网络,并且由DNS
解析器进行接收。 DNS
解析器会向根域名发起查询请求,要求返回顶级域名的地址。- 根
DNS
服务器会注意到请求地址的前缀并向DNS
解析器返com
的顶级域名服务器(TLD)的IP
地址列表。 - 然后,
DNS
解析器会向TLD
服务器发送查询报文 TLD
服务器接收请求后,会根据域名的地址把威DNS
服务器的IP
地址返回给DNS
解析器- 最后,
DNS
解析器将查询直接发送到权威DNS
服务器 - 权威
DNS
服务器将IP
地址返回给DNS
解析器 DNS
解析器将会使用IP
地址响应Web
浏览器 一旦DNS
查找的步骤返回了example.com
的IP
地址,浏览器就可以请求网页了
# 7.1.6 DNS查询类型
DNS
查找中会出现三种类型的查询。通过组合使用这些查询,优化的 DNS
解析过程可缩短传输距离。在理想情况下,可以使用缓存的记录数据,从而使 DNS
域名服务器能够直接使用非递归查询。
递归查询:在递归查询中,DNS
客户端要求 DNS
服务器(般为 DNS
递归解析器)将使用所请求的资源记录响应客户端,或者如果解析器无法找到该记录,则返回错误消息。

迭代查询:在迭代查询中,如果所查询的 DNS
服务器与查询名称不匹配,则其将返回对较低级别域名空间具有权威性的 DNS
服务器的引用。然后,DNS
客户端将对引用地址进行查询。此过程继续使用查询链中的其他 DNS
服务器,直至发生错误或超时为止。

缓存查询:为了提高DNS的查询效率,并减轻根域名服务器的负荷和减少因特网上的DNS查询报文数量,在域名服务器中广泛地使用了高速缓存。高速缓存用来存放最近查询过的域名以及从何处获得域名映射信息的记录。

由于域名到IP
地址的映射关系并不是永久不变,为保持高速缓存中的内容正确,域名服务器应为每项内容设置计时器并删除超过合理时间的项 (例如,每个项目只存放两天)。
不但在本地域名服务器中需要高速缓存,在用户主机中也很需要。许多用户主机在启动时从本地域名服务器下载域名和IP
地址的全部数据库,维护存放自己最近使用的域名的高速缓存,并且只在从缓存中找不到域名时才向域名服务器查询。同理,主机也需要保持高速缓存中内容的正确性。
理解两点
- 主机想要访问网站,首先访问本地的域名服务器,若是在本地的域名服务器中有,那么就直接返回即可。
- 若是在本地的域名服务器中没有,那就要对后续的域名器进行搜索
- 递归查询就是数据结构中树的深度优先搜索
- 迭代查询就是数据结构中树的广度优先搜索
# 7.2 DHCP协议
DHCP
的全称是 Dynamic Host Configuration Protocol 动态主机配置协议。使用 DHCP
就能实现自动设置IP
地址、统一管理 IP
地址配。也就是不管你是在开会还是在工位干活,都省去了手动配置 IP
地址这一步繁琐的操作,同时 DHCP
也大大减少了可能由于你手动分配 IP
地址导致错误的几率。
DHCP
与 IP
密切相关,它是 IP
网络上所使用的协议。如果你想要使用 DHCP
提供服务的话,那么在整条通信链路上就需要 DHCP
服务器的存在,连接到网络的设备使用 DHCP
协议从 DHCP
服务器请求IP
地址。DHCP
服务器会为设备分配一个唯一的IP
地址。
除了 IP
地址外,DHCP
服务器还会把子网掩码,默认路由,DNS
服务器告诉你。
# 7.2.1 DHCP服务器
现在,你不需要手动配置 IP
地址,也不再需要管理 IP
地址了,管理权已经移交给了 DHCP
服务器,DHCP
服务器会维护 IP
地址池,在网络上启动时会将地址租借给启用 DHCP
的客户端。
由于 IP
地址是动态的(临时分配)而不是静态的(永久分配),因此不再使用的 IP
地址会自动返回P地址池中进行重新分配。
DHCP
服务器通常为每个客户端分配一个唯一的动态 IP
地址,当该 IP
地址的客户端租约到期时,该地址就会更改。
唯一意思说的就是,如果你手动设置了一个静态 IP
,同时 DHCP
服务器分配了一个动态 IP
,这个动态IP
和静态IP一样,那么必然会有一个客户端无法上网。
DHCP
服务器维护的信息
- 网络上所有有效的 TCP/IP 配置参数
- 这些参数主要包括主机名 (Host name) 、
DHCP
客户端 (DHCP client) 、域名 (Domain name)、IP
地址(IP address) 、网关 (Netmask)、广播地址 (Broadcast address) 、默认路由(default rooter)。
- 这些参数主要包括主机名 (Host name) 、
- 有效的
IP
地址和排除的IP
地址,保存在IP
地址池中等待分配给客户端 - 为某些特定的
DHCP
客户端保留的地址,这些地址是静态IP
,这样可以将单个IP
地址一致地分配给单个DHCP
客户端
# 7.2.2 DHCP工作机制
DHCP 报文共有以下几种:
DHCP DISCOVER:
客户端开始DHCP
过程发送的包,是DHCP
协议的开始DHCP OFFER
:服务器接收到DHCPDISCOVER
之后做出的响应,它包括了给予客户端的 IP 租约过期时间、服务器的识别符以及其他信息DHCP REQUEST
: 客户端对于服务器发出的DHCPOFFER
所做出的响应。在续约租期的时候同样会使用。DHCP ACK
: 服务器在接收到客户端发来的DHCPREQUEST
之后发出的成功确认的报文。在建立连接的时候,客户端在接收到这个报文之后才会确认分配给它的IP
和其他信息可以被允许使用。DHCP NAK
:DHCPACK
的相反的报文,表示服务器拒绝了客户端的请求。DHCP RELEASE
:一般出现在客户端关机、下线等状况。这个报文将会使DHCP
服务器释放发出此报文的客户端的IP
地址DHCP INFORM
: 客户端发出的向服务器请求一些信息的报文DHCP DECLINE
:当客户端发现服务器分配的IP
地址无法使用(如IP
地址冲突时),将发出此报文,通知服务器禁止使用该IP
地址。

对上图做出解释
DISCOVER
:这个时期DHCP
客户没有IP
,同时也不知道DHCP
服务器,那么源地址就用0.0.0.0
来代替本机地址,通过广播来找DHCP
服务器。这个数据包中包含一个事务ID
便于后期找到客户。OFFER
:DHCP
服务器给客户回一个offer
。DHCP
服务器知道自己的IP
地址,所以此时的源地址是DHCP
服务器自己的IP
地址,由于客户没有IP
地址,所以也只能用广播以及之前的事务ID
来寻找客户。REQUEST
:由于DHCP
可能会收到多个offer
,所以这里的目的和源地址和第一次的时候一样。ACK
:当这个包到达客户,也就是说明以后分配好了IP
地址。0.5
倍租用期:DHCP
服务器分配的IP
都有时效性。所以在到达0.5
倍租用期的时候,DHCP
客户会进行租用的延期。
- 第一种情况:服务器返回
ACK
,说明得到新的租用期- 第二种情况:服务器返回
NACK
,说明服务器要收回IP
地址用于其他方面,此时客户立马进行新一轮的IP
授予- 第三种情况:由于
DHCP
协议在传输层用的是UDP
协议,所以可能会出先丢包问题。所以如果客户没有收到DHCP
服务器的回复,那么在0.875
倍的时候就会再次发送延期租用的请求。