计网的工作方式
分为边缘部分和核心部分。边缘部分里的端对端的通信,实际上是某个端(主机)的某个进程和另一个端(主机)的某个进程在通信。
端对端有两种方式,CS和p2p。 CS是客户端和服务端,一个服务器要处理来自很多客户端的请求。p2p是peer to peer,意为同等交流,每个主机既是客户又是服务器。
CS和P2P的不同:CS只有固定的有限服务器,因此请求的客户端越多,平均每个客户端的通信速率急剧下降;但P2P的每个主机既可以充当客户端又可以是服务器,因此通信的主机越多,平均每台主机的通信速率就更快,因为每台主机可以从其他主机同时接收,同时又可以传输给其他主机。
计网的分类
广域网WAN和局域网LAN的分辨,不能只看地理距离,要看它使用的通信技术。WAN使用交换技术,LAN使用广播技术。广播式网络共享公共通信信道,点对点网络使用分组存储转发和路由选择机制。
电路交换会独占资源,但是报文交换和分组交换属于存储转发交换,意为先存储之后查看要转发的地址,根据地址来选择最短或者最合适的线路。
速率
速率即为数据传输率,指的是连接在计算机网络上的主机在数字信道上传送数据位数的速率。单位是b/s、kb/s、Mb/s、Gb/s、Tb/s。(比特每秒)。千兆吉太,各自之间的换算是1000。
带宽
用来表示网络的通信线路传送数据的能力,通常是指单位时间内从网络中的某一点到另一点所能通过的“最高数据率”,单位是bps,即每秒可传输之位数。
吞吐量
表示在单位时间内通过某个网络(或信道或接口)的数据量,单位仍然是b/s、kb/s、Mb/s.
时延
也叫延迟,指的是数据(报文/分组/比特流)从网络的一端传送到另一端所需的时间.
发送时延:从发送分组的第一个比特算起,到该分组的最后一个比特发送完毕所需的时间.受数据比特数和发送快慢影响,等于数据长度除以信道带宽(发送速率)
传播时延:取决于电磁波传输速度和链路长度,等于信道长度除以电磁波速.
排队时延
处理时延
高速链路指的是提高信道带宽从而降低发送时延的链路,无法影响到传播时延.
时延带宽积
时延带宽积 = 传播时延 X 带宽 ,单位是bit.
往返时延 RTT
从发送方发送数据开始,到发送方收到接收方的确认为止,总共经历的时延,等于传播时延的两倍+末端处理时间.
往返时延不包含发送时延。
利用率
信道利用率:信道上有数据通过的时间➗数据总共的通过时间
网络利用率:信道利用率加权平均值
实体
某一层中的活动元素称为该层的实体,同一层的实体叫做对等实体。
协议
对等实体想要进行数据交换,就需要建立一套规则,这个规则就叫做网络协议。
协议由三个要素组成😊
| -- | -- |
|---|---|
| 语法 | 规定数据的格式 |
| 语义 | 规定要完成的功能 |
| 同步 | 规定操作的顺序 |
| -- | -- | -- |
|---|---|---|
| SDU | 服务数据单元 | |
| PCI | 协议控制信息 | |
| PDU | 协议数据单元 |
下层把上层已有的数据和协议包装在一起作为下层的服务数据SDU,再添加下层这一层的协议PCI,就构成了下层的协议数据单元PDU。
对于OSI模型,主机A的应用层首先准备好一个要发送的信息,经过应用层、表示层、会话层、传输层、网络层、数据链路层、物理层,每一层依次贴上一个标签,在物理层发送出由01组成的比特流。比特流首先抵达中间系统,中间系统的物理层、数据链路层、网络层依次撕开标签,检查和确认这个信息要执行的操作和要去往的地方。之后再经过中间系统的网络层、数据链路层、物理层回到比特流,物理传输到主机B的物理层,再一步一步还原至应用层,成为一条应用层的信息。
各层作用
应用层
所有需要网络流量才能使用的程序,就是应用层的范畴。
表示层
把底层传输的01码翻译成应用层能给人看的数据格式。 对数据进行加密解密、压缩恢复。
会话层
向表示层实体提供建立连接的服务,并在连接上有序地传输数据。
网络边缘与核心
主机及其进程是网络边缘,各类交换机和路由器是网络核心。核心构成主要通信网络,允许边缘接入,使得任意两个边缘之间可以通过核心来达到通信的目的。
网络核心的作用便是数据交换,它实际上是由许多交换机和路由器组成的分布式系统。
通信连接方式
| -- | -- | -- | -- |
|---|---|---|---|
| 面向连接 | TCP | 主机在通信前先互相确认并来到准备状态 | 通信的维护只在端侧的主机,网络核心不参与维护 |
| 无连接 | UDP | 通信前不连接,每段数据独立发送 | 传输的数据可能丢失,但是整体速率快且可控 |
通信方式
电路交换
通信前建立专有的独占线路。性能有保障。
分组交换
将要传的数据分成很多部分,每部分都叫一个分组。将分组从路由器传到相邻的路由器,依次从source传到target。新增了存储时间和排队时间,但是用时间换来了共享通信。
传输层提供服务
应用层和传输层之间的层间接口所必须提供的信息。
Internet传输层提供的服务分为TCP和UDP两种。
| -- | -- |
|---|---|
| 传的啥 | 要传输的报文,对于本层来说是SDU |
| 谁传的 | source主机的IP,和哪个TCP(UDP)端口 |
| 传给谁 | target主机的IP,和哪个TCP(UDP)端口 |
TCP socket
应用程序比如浏览器、电子邮件、文件传输服务器等产生的数据,会通过传输层协议进行传输。而应用程序是不会和传输层直接建立联系的,而是有一个能够连接应用层和传输层之间的套件,这个套件就是 Socket。
命令行输入 netstat -ano ,得到的数据里面,每一行包含本主机的IP和端口号、通信对象的IP和端口号、状态和PID,这些合起来称为一个 socket 。(中科大老师:本机的IP加端口号+通信对象的IP+端口号=本机一个socket)
根据一个独一无二的 socket ,操作系统就能够知道通信的对象,反过来根据对方和自己的IP和端口号也能找到相应的 socket ,从而找到这个 socket 对应的应用进程。socket是本地标识的,是仅存在于应用层和传输层之间的一个约定,代表本主机的某个进程与另外一个主机的某个进程之间的会话关系。 应用进程只使用 socket 去发数据,操作系统就能辨别出要从哪发到哪。
B接收A主机发送的数据,根据收到的A的IP和端口号和已知的自己的IP端口号,就可以查询到本地对应的一个唯一的 socket ,根据这个 socket 就可以查到相应的应用进程对应的进程编码 PID ,然后把数据给具有这个 PID 的应用进程。
UDP socket
原理同上。
但是由于使用UDP服务的两个进程在通信之前无需建立连接,所以一个主机相邻的两个报文很可能发给不同进程。所以 UDP socket只包含本主机的 IP 和端口号。
如何使用 socket
无论使用 TCP 还是 UDP 服务,要进行数据传输的时候都需要应用层向传输层给出“传的啥、谁传的、传给谁”这三个信息。
在使用 TCP 服务时,由于 TCP 是要先建立连接的,因此在传输数据之前本机已经知晓了目标主机的 IP 和端口号。为了减少传递数据的量,我们把本机的 IP 和端口号、目标主机的 IP 和端口号组合起来,作为 TCP socket。所以应用层向传输层只需要提供两个信息:TCP socket 和数据。
在使用 UDP 服务时,由于使用UDP服务的两个进程在通信之前无需建立连接,所以 UDP socket只包含本主机的 IP 和端口号。但是在发送数据之前仍然需要提供目标主机信息。因此应用层向传输层需要传输三个信息:UDP socket 、数据、目标主机的 IP 和端口号。
Web
Web页是由一些对象组成,包含一个基本的HTML文件,该基本HTML文件又包含若干对象的引用。搜索引擎通过 URL 访问基本的 HTML 文件勾勒出一个基本的网页框架,然后访问 HTML 文件里面的超链接(也是URL)来完善网页。
应用层协议
HTTP,SMTP,DNS等等都是。
HTTP 协议
HTTP 是建立在 TCP 服务上的协议。
终端与服务器首先要建立 TCP 连接,然后终端发送 HTTP 请求让服务器的监听socket收到,然后服务器通过连接socket用 HTTP 协议的报文发送回终端来响应请求。
www.cnblogs.com/liangjf/p/9…
监听socket与连接socket不一样,是分工合作的。监听socket,是服务器作为客户端连接请求的一个对端,只需创建一次能够让客户端请求到有这个端点就ok,所以监听socket存在于服务器的整个生命周期, 不需要每个连接都创建一个新的监听socket出来, 没必要呢。已连接socket是客户端与服务器之间已经建立起来了的连接的一个端点,生命周期仅仅是这一个连接所存在的时间。
响应时间模型
首先一个 RTT 用来发起和确认TCP 连接,一个 RTT 用来发送并等待 HTTP 响应,再加上文件上传的时间,总共是两倍RTT加上发送时延。
流水线模式请求
客户端可以在发送上一个 HTTP 请求后还未收到服务器的响应时,再次发送一个请求。即客户端遇到一个引用对象就立即产生一个请求。
HTTP 报文
请求报文
| -- | -- | -- |
|---|---|---|
| 请求行/起始行 | 方法+URL+协议类型 | 方法有Get,Post,Head ; 协议类型是HTTP1.0或1.1 |
| 头部行/首部行 | ||
| 回车 |
响应报文
| -- | -- | -- |
|---|---|---|
| 状态行/起始行 | 协议类型+状态码+状态描述 | 状态码可以辨别服务器响应之后的状态 |
| 头部行 | ||
| 数据 |
因为HTTP是运行在TCP服务上的协议,而TCP并不维护所传数据的完整性(即source的TCP收到来自应用层的两个15k字节流,但target的TCP可能给应用层提供的是一个30k的字节流)。因此请求报文和响应报文存在的意义是为了辨别连续数据里面每一段的起始和终止。
cookie
因为 HTTP 是无状态的,所以为了协助 Web 保持状态,所以诞生了 Cookie 。
无状态:在数据交换完毕后,服务器端和客户端的链接就会关闭,每次交换数据都需要建立新的链接。
当小杜的主机第一次访问京东时,我的主机第一次发送的请求报文是很普通的请求报文。服务器接收到之后,这个Web站点产生了一个唯一的ID,同时以这个ID作为索引在京东的数据库里面产生一个项。然后服务器返回给我响应报文,此时第一次收到的响应报文中含有一个cookie的首部行。我的主机根据这个首部行在本地存储一个文本用来存储cookie,这个cookie由浏览器管理。第二次小杜访问京东时,我发送的请求报文就含有一个cookie的首部行,此时服务器根据这个cookie,就能找到唯一匹配的数据,然后传输相应的个性化数据。当然,第二次开始响应报文就不含有cookie了。
记住登录状态、查询到账号内信息、个性化推荐,都源于cookie。
用户代理
我们是通过客户端代理来访问某个应用,而不是直接访问应用。
用户通过代理把要发送的Email上传到邮件服务器,邮件服务器把自己队列中的邮件依次发送到相应的目标邮件服务器(发送Email报文使用的是SMTP协议)。目标邮件服务器把邮件放到对应用户邮箱的目录当中,目标客户再调用客户代理阅读邮件。
Web缓存
Web缓存是指一个Web资源的副本。缓存第一次把这个请求的URL的内容保存一个副本,下一个请求如果是相同的URL,一般会根据网站是否更新来决定是直接使用缓存来响应访问请求、还是向服务器再次发送请求。如果请求的对象不在缓存,那么缓存会访问服务器,把数据回传给主机同时保存一个副本作为缓存。
即在主机和服务器之间有一个代理服务器也叫缓存,主机和服务器必须且只能通过代理服务器通信。每次主机发送请求,首先到达代理服务器,再由代理服务器根据缓存机制来决定用缓存来回应请求还是用访问服务器来回应请求。
由于存在28定律(八成的人请求的总URL只占两成),因此如果能在缓存就命中客户端请求,就能显著降低服务器的压力。要知道随着流量逼近带宽上限,排队时延可以视为指数级增长。所以缓存的存在降低了流量,很大程度上让排队时延保持在人难以觉察的时间尺度上。
SMTP 与 HTTP
SMTP采用持久连接,而HTTP采用不持久连接,所以诞生了cookie。
HTTP的一个报文至多有一个对象,当然这个对象可以包含其他对象的链接,这不算多个对象;但是SMTP可以把多个对象包含在一个报文之中。
DNS
网络中的主机和服务器都是根据IP地址来标识和寻址的,但是对于想要建立通信的人类来说,域名显然是更有意义且好记的。为了让计算机能够辨别域名并转化为IP地址,DNS系统应运而生。应用进程一拿到域名,就知道和哪一个主机或Web服务器建立连接。
规范IP便于管理,域名便于用户访问。
三件要做的事:首先命名(标识),其次转换(域名到IP,方便寻址),最后维护(域名和IP都需要删除增加)。
尽管DNS是网络中一个极其重要的功能,但是它是在网络边缘中主机的应用层实现的。
分层命名、分布式数据库、运行在UDP服务上(即时性需求大于稳定性),使用端口号53。
域名的管理
一个域管理其下的子域。
创建一个新的域,必须征得所属域的同意。
域的划分是逻辑上的,不是物理上的。同一个域下的主机可以不在同一个局域网(物理网上可以没有任何关系),一个网络的主机不一定在同一个域。
高级域要知道次级域的名称,还要知道次级域服务器对应的IP地址。
域名树如何划分为zone
域名树内的节点可以随意划分,要求是不能交叉和跳过。
每个区域zone都有一个名字服务器,维护所在域的权威信息。
TTL (tome to live)
TTL是生存时间,决定了资源记录应当从缓存中删除的时间。
前面说到“本地DNS服务器先查找自己的缓存记录”,为什么要新增缓存呢?因为如果小杜要访问京东服务器,那么如果小杜主机的本地DNS服务器有京东的域名到IP地址的映射,那么我就能很快得到IP地址并进行访问,不需要向根域名服务器一步一步请求。那为什么又要删除呢?因为这个域名对应的服务器可能维护,迁移到了另一个IP上,所以定时删除可以保持本地缓存与真实IP的一致性。
如果资源是权威信息,那么它的ttl是无限大,不能被删,永久存在于数据库。
如果是缓存,那么需要定期删除,一般默认ttl是两天。
本地名字服务器 Local Name Server
每个ISP都有一个本地DNS服务器。当一个主机发起一个DNS查询时,查询会被送到本地DNS服务器,由它将查询转发到层次结构中。
运行过程
首先查找电脑上的DNS缓存列表,如果有记录,那么直接返回对于IP地址,否则进行下一步;
查找电脑上的HOST文件的映射关系,如果有记录,那么返回对于IP地址,否则进行下一步;
查找互联网线路供应商的本地DNS服务器(即中国电信、中国移动或中国联通),本地DNS服务器先查找自己的缓存记录,如果有记录,那么返回对于IP地址,否则本地DNS服务器向根域名服务器发生请求;
根域名服务器收到请求后,查看是.com顶级域名,于是返回.com顶级域名服务器的IP地址给到本地DNS服务器;
本地DNS服务器收到回复后,向.com顶级域名服务器发起请求;
.com顶级域名服务器收到请求后,查看是.baidu.com次级域名,于是返回.http://baidu.com次…
本地DNS服务器收到回复后,向.baidu.com次级域名服务器发起请求;
.baidu.com次级域名服务器收到请求后,查看是自己管理的域名,于是查看域名和IP地址映射表,把http://www.baidu.…
本地DNS服务器收到回复后,向电脑回复域名对应IP地址,并把记录写入本地DNS服务器的缓存里;
电脑收到回复后,使用IP地址访问网站,并把记录写入电脑DNS缓存中。
首先名字空间划分为几百个顶级域,每个顶级域之下又有若干二级域,其下又有三级域,再往下还有。最顶上是根名字服务器,每次查询都需要从根往下找。
递归查询:递归查询的方式主要是,当应用需要dns服务,发送到本地dns,本地dns发送到根dns,根dns通过dns数据库中的ns(对应域的权威名字服务器)表项查找到对应域,发送dns,一路查询到主机。
P2P系统
每个peer在不同的通信线路上,既是一个Web客户端,又可以是一个瞬时Web服务器。
由于是分布式系统,没有一个集中处理请求的服务器,因此可靠性高。
| -- | -- | -- |
|---|---|---|
| CS | 要搭建一个专用的服务器之后才能提供服务。可拓展性差。 | 各个节点的下载时间随着客户端数量的增加线性增加,瓶颈是服务器的上载带宽 |
| P2P | 用数量很少的服务器搭建起通信网,剩下的都是大量peer节点相互服务。很容易扩展到极大规模。 | 随着规模增大,平均每个客户端下载的时间增长很小。 |
非结构化P2P(Napster的由来)
相比非结构化P2P,最大的不同是:非结构化P2P的节点所构成的网络是随机的、无序的,而结构化DHT可以构成一个环、树等等关系。
| -- | -- | -- | -- |
|---|---|---|---|
| 特点 | -- | -- | 不足 |
| 集中化目录 | 每个peer在上线时都向目录告知:我上线了、我的IP、我拥有的资源文件 | 在客户端提交文件查询到目录服务器,目录知晓哪些节点拥有文件并返回其IP,再由客户端向目标客户端提交请求文件。 | 尽管文件传输是P2P,但定位内容是高度集中的。可能单点故障引发宕机、具有性能瓶颈。 |
| 完全分布式 | peer小杜下载P2P软件的同时会收到一个已经在P2P网络中的部分peer的列表。小杜会向这些已知的peer发送ping指令,每个peer在收到我的ping后,会回应我同时转发我的ping。然后由小杜在这些给出回应的peer里面随机挑选一部分作为我在这个P2P网络里面的固定的直接建立通信的peer。 | 首先一个客户端在已有的TCP连接上,向自己所有的已建立通信的peer发送文件查询,source客户端的每一个peer又再向自己其余的peer转发查询(一传十十传百),当在网络中某个peer命中查询后,该peer以反方向返回查询命中及相关信息,让source得到target的IP。 | 唯一需要解决的问题是查询何时停止。可以用规定转发次数或记录已查peer来解决。 |
| 混合 | 组长相当于本组内的目录服务器。 | 存在类似两层D+树的结构。每个peer要么是组员要么是组长。组员只与其组长通信,组长与其所有组员和一些其他组长通信。类似unordered_map,根据键入的描述匹配到目标文件的哈希值,发送的查询请求都是哈希,能找到唯一确定的对应文件 | 组内是集中式,组长与组长间是分布式,综合两者优点。 |
BT的分享率
为了用规则而不是自觉来实现我为人人人人为我的目的,设立了分享率这一概念。
详见 zhuanlan.zhihu.com/p/364041702 。
对己方提供下载带宽多的peer,再接下来一两个服务周期可能会得到己方较多的上载带宽,之后己方会随机挑选一些peer来优先服务。
BT下载:首先小杜通过搜索引擎下载Torrent文件,这个文件里面告诉小杜 Tarcker 服务器的地址。小杜再向 Tarcker 服务器发起请求, Tarcker 服务器便在自己的存储里找拥有这个 Torrent 文件的peers的地址返回给小杜,同时把小杜加入 Tarcker 服务器的存储。当小杜收到回应后,会通过完全分布式的方式加入这个上下载网络的通信中,就可以开始同时向多个peer下载这个文件不同的块了。这期间会校验各个块的哈希值来确保完整和不重复。当小杜下载完之后,小杜不会关闭BT客户端,而是让自己作为这个上下载网络中的一个peer来服务他人,以确保下次我需要下载时可以得到更高的优先级。
多媒体
视频:固定速度显示的图像序列。
数字化图像:图像是像素的阵列,每个像素用若干bit来表示。**编码时,使用空间冗余和时间冗余来降低编码的bit数。
| -- | -- |
|---|---|
| 空间冗余 | 同一帧内大片像素可能几乎一致,可以用一组同样的bits来形容一大片区域。 |
| 时间冗余 | 相邻帧之间只需要记录变化部分的bits即可。 |
流式服务
简介:流媒体是指将一连串的媒体数据压缩后,把数据以流的方式分段从服务器传输到客户端,使得实现即时预览。
实现过程:
服务器将音视频文件分割成多个块。每个块独立存储,并把每个块都在不同码率上编码。同时设立一个告示文件,文件里面提供不同块的URL。
客户端首先获取告示文件,并在一个时刻请求对应的块。同时客户端会周期性地测量服务器到客户端的带宽,根据当时的可用带宽动态选择不同码率的视频块。
服务器如何通过网络向大量用户同时流化视频内容呢?
| -- | -- | -- |
|---|---|---|
| 解决方案 | 特点 | 评价 |
| 单个或少数mega—server | 服务器到客户端路径上跳数多,带宽被路径上最小的带宽制约,单点故障会导致宕机,存在性能瓶颈和重复资源的浪费,造成服务器周边网络拥塞 | 简单,但不可拓展 |
| CDN | 在全球部署很多cash节点,预先把内容部署在cash里,用户访问域名的时候定位到离用户最近(提供服务最好)的cash节点,由这些节点来提供服务。 | 运行在应用层,而且运行在网络边缘。 |
TCP socket 编程
1.服务器进程必须运行,创建一个监听socket,该socket和自己的IP和端口号进行捆绑,在监听socket上阻塞式的等待接收客户端的连接。
2.客户端创建本地的socket,第一步要对socket指明是TCP还是UDP还是其它,然后操作系统会把socket默认地捆绑到本地的端口,再指明服务器的ip和端口进行连接。
3.用户端通过TCP实体向服务器发送请求 ,使服务器解除阻塞式等待,返回一个连接 socket 的值(与监听 socket 不一样,但是捆绑在同样的IP和端口号上),这个连接 socket 与客户端已创建的socket连接。
4.连接API调用有效时,客户端与服务器建立了TCP连接,即可以通信啦。
5.通信时在socket中读写(相当于文件)。
以下是java中socket的结构体:
public abstract class SocketImpl implements SocketOptions {
/**
* The IP address of the remote end of this socket.远程主机的ip地址
*/
protected InetAddress address;
/**
* The port number on the remote host to which this socket is connected.远程主机的端口
*/
protected int port;
/**
* The local port number to which this socket is connected.本地端口
*/
protected int localport;
/**
*实际还有一个本机的ip地址,被省略掉了
*/
}
以下是解析域名到获得IP地址的结构体:
struct hostent
{
char *h_name;//主机的域名
char **h_aliases;//主机的很多别名
int h_addrtype;
int h_length;//地址长度
char **h_addr_list;//IP地址的列表
}
以下是cpp中的socket结构体:(把IP地址和port捆绑一起的数据结构。)
struct sockaddr_in
{
short sin_family;//地址族,标明是用在TCPIP还是RDS中通信。
u_short sin_port;//端口号
struct in_addr sin_addr;//IP地址
char sin_zero[8];//对齐
}
把在hostent中得到的IP地址拷贝到sockaddr_in的IP地址部分中,sockaddr_in代表的是通信过程中的一个端节点。
端口与进程的关系:多个进程在通信两端的某一端可以使用同一个端口号,但是另一端的IP和端口号至少一个不一样,才能区分不同的socket。详见 www.cnblogs.com/welen/artic… 。服务器的IP和Port可以保持不变,只要客户端的IP和Port彼此不同就OK啦。
UDP socket 编程
没有握手。发送端在每一个报文中明确地指定目标的IP地址和端口号,服务器必须从收到的分组中提取收到出发送端的IP地址和端口号。
UDP传送的数据可能乱序也可能丢失。为客户端提供的是不可靠的字节组的传送服务。
UDP没有监听socket和连接socket之分。
过程:1.服务器进程必须运行,创建一个socket,该socket和自己的IP和端口号进行捆绑,在socket上阻塞式的等待接收客户端的连接。
2.客户端创建本地的socket,第一步要对socket指明是UDP,然后操作系统会把socket默认地捆绑到本地的端口,再指明服务器的ip和端口进行连接。
3.用户端通过UDP实体向服务器发送请求 ,请求里面包含待处理数据、客户端的socket和目标服务器的IP与端口号。服务器的这个socket解除阻塞式等待,根据接收到的请求得到服务器数据要传送的目标地址(也就是客户端的IP和端口号)。之后直接操作完数据之后发送回客户端。
4.通信时在socket中读写(相当于文件)。操作完毕之后回到等待状态或关闭socket。
传输层的作用
使得逻辑上是应用层的进程与进程之间进行通信(而不是主机和主机),物理上是传输层及以下互相配合提供服务。
多路复用/解复用
在发送方主机多路复用:
从多个套接字接收来自多个进程的报文,根据套接字对应的IP地址和端口号等信息,对报文段用头部加以封装。
在接收方主机多路解复用:
根据报文段的头部信息中的IP地址和端口号,将接收到的报文段发给正确的套接字,从而转发给对应的应用进程。
在UDP中,如果两段报文具备相同的目标IP和目标端口号,那么即使源IP或源端口号不同,仍会被传到相同的目标socket。
多个进程在通信两端的某一端可以使用同一个端口号,但是另一端的IP和端口号至少一个不一样,才能区分不同的socket。
可靠传输数据rdt的描述
能干什么:数据可以通过一条可靠的信道进行传输,借助于可靠信道,传输数据比特就不会受到损坏或丢失,而且所有数据都是按照其发送顺序进行交付。
rdt_send()和deliver_data()是传输层与应用层之间的接口,udt_send()和udt_rcv()是传输层的协议实体跟下层的接口形式。
底层的不可靠性决定了协议的复杂性,催生了检查、奖惩等等机制来确保数据对于应用层来说是可靠的。
双向数据传递实际上是两个单向数据传递,所以我们只考虑单向数据传输,但是控制信息是双向流动的。
rdt协议
由于IP协议传输的数据是不可靠的,因此需要我们使用一种可靠数据传输协议来实现数据的可靠传输如TCP协议,TCP采取的许多原理正是rdt协议。
小杜觉得很形象很生动的解释 blog.csdn.net/Sqrt1230/ar… 。
rdt 1.0
假设:为了更好的理解,首先假设底层信道完全可靠(不像IP协议那样不可靠),即底层信道既不会发生比特差错(0变1,1变0)又不会发生分组丢失,并且同时假设接收端的接受速率和发送端的发送速率一样快,没必要通知发送端控制发送速率。
发送端:首先传输层在等待来自上层的调用。当上层要发送数据时调用本层,然后本层将上层数据包装并产生分组,再将分组发送到底层通信中。之后发送端的传输层回到一开始“等待来自上层的调用”的状态。
接收端:首先传输层在等待来自下层的调用,当接收到下层信道发送来的分组时,从分组中取出数据,再将数据交付给上层,之后传输层回到一开始“等待来自下层的调用”的状态。
发送端和接收端的传输层在传输时,接收方不必要向发送方反馈任何消息,并且接收方没必要通知发送方控制发送速率。
rdt 2.0
rdt1.0是完全理想状态的,实际过程中肯定会发生比特差错。我们先保留分组不会丢失这个假设,引入比特差错。
自动重传请求协议 ARQ:发送端向接收端重新发送出现比特差错的分组。
停等协议:发送端在没有确信接收端已正确接收当前分组时,不会发送新的数据。
概述:发送端每传一个分组,就会停下来等待接收端的确认信号:是肯定确认ACK还是否定确认NAK。如果接下来接收到ACK,那么会继续发送下一个分组;如果接收到的是NAK,那么会把这个分组重新发送一遍。
发送端:首先传输层在等待来自上层的调用。当上层要发送数据时调用本层,然后本层将上层数据包装并产生分组,再将分组发送到底层通信中。之后发送端的传输层进入“等待ACK或NAK”的状态:如果接收到NAK会重新发送该分组,如果接收到ACK会回到“等待来自上层的调用”的状态。
接收端:首先传输层在等待来自下层的调用,当接收到下层信道发送来的分组时:如果数据未发生比特差错,那么从分组中取出数据将数据交付到上层,然后产生ACK分组并向发送端发送ACK;如果数据发生比特差错,那么产生NAK并向发送端发送NAK。当发送完ACK或NAK后,传输层回到一开始“等待来自下层的调用”的状态。
当发送端处于“等待ACK或NAK”状态时,不会从上层获取更多的数据,也不会发送新的数据,因此rdt2.0是停等协议;并且当发送端收到否定确认时会重新发送该分组,因此rdt2.0是ARQ协议。
rdt 2.1
在不考虑分组丢失的情况下rdt2.0看似已经近乎完美了,但是其实它有一个致命的缺陷就是如果ACK或NAK分组发生了比特差错,rdt2.0是没有相应的处理措施的,于是我们引入了rdt2.1。
在rdt2.1中,针对ACK或NAK分组发生比特差错的情况,如果发送方收到了含糊不清的ACK或NAK分组(发生比特差错)时,只需要重传当前分组既可。然而这种方法会产生一个问题,就是接收方不知道发送方是否正确地收到了ACK或NAK分组,因此接收方无法事先确认它收到的是新的分组还是一次重传。解决这个问题的简单办法就是让发送方对其数据分组编号,并在分组中添加一个序号字段。这样接收方就可以根据分组序号来判断收到的是新的分组还是一次重传。
发送端:发送编号0的分组后,会等待编号0的确认分组:如果没有损坏且为ACK分组,无任何动作,等待上层协议;如果没有损坏且为NAK分组,重发编号为0的分组;如果损坏,无论是ACK还是NAK,重发编号为0的分组。
接收端:假设一开始在等待编号0分组的状态。如果接收到编号0分组且无损坏,那么产生并发送给ACK分组;如果接收到编号1分组且无损坏,那么也是产生并发送ACK分组;如果接收到损坏的分组,那么产生并发送NAK分组。
如果接收端在等待编号0分组时,接收到了编号1分组,首先我们可以知道的是这个状态是从接收编号1分组的状态来到的,说明接收到的上一个编号1分组是无误并且发送了ACK确认的。我们可以推测出,上一个接收到的分组也是编号1,而这一个还是编号1。根据机制是不可能跳过一个编号0分组的,所以只能是这两个编号1分组是同一个分组,说明上一次发送的ACK分组产生了比特差错,导致发送端把编号1分组再发送了一遍。此时发送端滞后一个分组,仍然停留在“等待编号1的ACK或NAK”的状态,因此为了得到这一个编号0分组,接收端要再发送一个ACK分组来让发送端进入“发送编号0”的状态。发送端接收到ACK分组后,会接着发送编号1之后的编号0分组,也就是接受端在等待的这个分组。
rdt 2.2
为了更加简明,我们不使用NAK分组,通过给ACK分组加上序号来实现与rdt2.1相同的效果。发送方连续接收到对同一个分组的两个 ACK 后,就知道接收方没有正确接收到跟在被确认两次的分组后面的分组。
rdt2.2与2.1的区别就在于去掉了NAK,而在ACK分组中显式指出分组编号。
发送端:发送编号0的分组后,会等待编号0的确认分组:如果没有损坏且为ACK0分组,无任何动作,等待上层协议;如果没有损坏且为ACK1分组,重发编号为0的分组;如果损坏,重发编号为0的分组。
接收端:假设一开始在等待编号0分组的状态。如果接收到编号0分组且无损坏,那么产生并发送给ACK0分组;如果接收到上一个的编号1分组且无损坏,那么也是产生并发送ACK1分组;如果接收到损坏的分组,那么产生并发送AKC1分组。
实际上就是省去判断NAK还是ACK的过程,用一个字符来表示接收端最近一个接收完毕的分组。
rdt 3.0
我们回归到符合实际的情况,即既会产生比特差错,又会产生分组丢失。那么如何解决分组丢失的问题呢?诞生了这么一个机制:发送端发送一个分组同时启动一个计时器,如果在计时器倒计时结束之前收到了正确的ACK响应,则中断定时器,进入准备接收来自上层的下一次调用。如果倒计数定时器超时,则发送方认为分组丢失,向接收方重传该分组,并且重新启动定时器。
rdt3.0是基于rdt2.2之上的。
计数器一般会设置为RTT的三倍左右,或者根据最近的吞吐量动态调节。
缓冲区
发送端:为了实现检错重发和超时重发。
接收端:发送端发送的速率和接收端上应用层使用的速率不一致,需要缓冲来对抗。
滑动窗口协议
SW:server window RW:receiver window
当SW=1,RW=1,此时是停止等待协议。SW(stop&wait)
当SW>1,RW=1,此时是Go back N (GBN)
当SW>1,RW>1,此时是Select repeat(SR)
发送端每发送一个分组,滑动窗口的前沿就会向前移动一位,直到到达缓冲区的最大空间。
发送端的滑动窗口用于存放已发送但还没有得到接收端确认的分组.当接收端传输层接收到来自上层的分组时,首先会检查窗口是否已满,若已满则拒绝,若未满则打包发送。
GBN:
发送端的窗口有一个计时器,第一次发送时会启动。此后每当接收到一个正确的ACK(GBN)就滑动窗口前移并重启计时器。如果没法向前滑动,说明分组或ACK出现丢失,会引发计时器倒数超时,此时会把窗口内的所有分组重新发送一遍。
接收窗口就是接收缓冲区。只有分组序号在接收窗口内的分组才能被接收,若序号在接收窗口之外则会被直接丢弃。所以如果接收窗口大小=1,那么只能够顺序接收,每次发送的确认是按顺序收到的最后一个分组的ACK。
选择重传SR协议:
接收端的缓冲区大小>1,每收到一个分组,就返回对应的ACK。只有当接收到接收端窗口下沿的分组时,接收端滑动窗口才会前移,但是只要在窗口内的分组都可以被正常接收并返回对应的ACK。如果已到达的分组是乱序,那么会被缓存,等待能形成有序(即接收到序号更小的分组)的时候再转发到应用层。
发送端的窗口每发送一个分组就启动一个独立的计时器。发送端窗口只有当接收到下沿分组的ACK时才会前移,但是窗口内的分组的ACK都可以正常接收。如果接收到某个分组的ACK,那么就关掉对应的计时器;如果某个分组的ACK超时仍未接收到,发送端就会把这个分组重新发送一遍。
| -- | -- | -- |
|---|---|---|
| 类型 | 特点 | 适用 |
| GBN | 所需缓存和管理资源少,但出错时回退重发代价大 | 出错率低的场景 |
| SR | 出错重传代价小,但所需资源较大 | 延迟大、带宽大的场景,因为一旦出错代价很大 |
TCP概述
- 点对点:一个发送方、一个接收方,不存在一对多或多对一。
- 全双工数据:交互的主机双方,既可以是发送方,又可以是发送方,数据是在交互方双向流动的。
- 面向连接:在数据交换之前,通过握手(交换控制报文)在通信的双方主机上维护这个连接双方的一些状态。
- 可靠的、按顺序的字节流。
- 流水线:TCP拥堵控制和流量控制设置窗口大小。
- 会建立发送和接收缓存。
- 流量控制:发送方不会淹没接收方。
最大报文段长度 MSS
参考blog: blog.csdn.net/pang5356/ar… 。
由于网络存在一个最大传输单元MTU(指的是发送端主机的链路层能发送最大帧的长度),一般MTU的值是1500字节。而一段报文里面既要包含TCP首部也要包含有效数据,这两部分加起来就是MTU,所以MSS就是最大传输单元减去首部字节得到的最大可载荷数据长度。
当应用层给到传输层的数据很长的时候,必须分割成一个个MSS大小的数据段,之后每个MSS大小的数据加上TCP的头部再加上IP的头部,就正好能被封装在一个物理网络的MTU之中。
序列号和确认号
在TCP之中,每一段数据的首个字节,其在应用层给传输层的总数据之中的offset,称为这个分组的序列号。
假如发送方要发送5000字节的数据,而MSS为1000字节,那么第一个报文段的序号为0,第二个报文段的序号为1000,第三个报文段的序号为2000,以此类推。
确认号是代表接收方期望下一个收到分组的序列号。如果主机A向主机B发送确认号500,就表示主机A想收到主机B的序号为500的分组数据。类似把顺序到来的最后一个分组的ACK返回。
TCP的往返延时(RTT)和重传超时时间RTO
TCP与rdt一样,都采用超时/重传机制来处理报文段的丢失问题。那么如何设置TCP超时值呢?
我们知道RTO必须大于该连接的RTT。但是RTT是变化的。如果RTO太短会造成不成熟的超时,这就会导致不必要的重传;而RTO太长则对数据段丢失响应慢。TCP协议使用自适应算法以适应互联网分组传输时延的变化。这种算法的基本要点是TCP监视每个连接的性能(即传输时延),由此每一个TCP连接推算出合适的RTO值,当连接时延性能变化时,TCP也能够相应地自动修改RTO的设定,以适应这种网络的变化。一般RTO略大于RTT。
TCP的发送和重传机制
是GBN和SR的结合体。只为窗口的下沿分组设定计时器(这点像GBN),当超时时会重发窗口下沿的分组(这点像SR)。当计时器的下沿抵达上沿时,代表窗口长度归零,此时计时器关闭。
当发送端接收到连续三个冗余的ACK时,证明这个报文段丢失了,会在超时计时器触发之前把这个报文段进行重传。
另外还要牢记,TCP里边的ACK是确认号,指的是接收端跟发送端说的“下一个我想要接收到的分组的序列号”。
TCP产生的ACK
| -- | -- |
|---|---|
| 接收方的事件 | 动作 |
| 所期待序号的报文段按顺序到达,且在期望序号以前的数据都已经被确认 | 对下一个按序报文段的到达等待500ms。若在这个时间内没到达,则发送下一个报文段起始位置的ACK |
| 所期待序号的报文段到达,且上一个按序报文段的计时器正在等待 | 立即返回且只返回一个累计的ACK |
| 比期待序号大的报文段到达 | 缓存这个乱序的报文段,发送与上一次重复的ACK,指明接收端正在期待的报文段 |
| 接收到数据gap之中部分或全部报文段 | 优先发送空缺部分的ACK,数据能按序排列后发送下一个报文段的ACK |
TCP流量控制
接收端控制发送端,不让发送端发送得太多太快,防止出现接收端缓冲区溢出的情况。
那要如何实现呢?接收方在ACK的头部的rwnd字段“通告”接收方缓冲区的空闲buffer的大小。于是发送端会限制己方未确认的字节数不大于rwnd的值。
TCP连接管理
若仅有两次握手是不行的。由于超时重发,那么接收端接收到的顺序可能是一个连接请求、一个数据段、连接关闭、再一个连接请求、再一个数据段。然而第二次接收到的可能仅仅是第一次的重发,接收端却为此建立了通信分配了空间甚至接收了数据。看起来很合理,实际上却浪费了很多时间空间。
所以确立了三次握手的机制。首先客户端发送连接请求,然后服务端返回同意连接、随机的开始序号。最后客户端确认服务端的序号,并返回自己的随机开始序号。
这样可以避免以上情况。因为第二次接收到同一个连接请求时,对于客户端来说连接已经关闭了,所以不会返回确认,因此通信也就不会建立起来。
还有一种情况,如果两端多次连接使用的是同样的端口号,那么如果在第二次连接的过程中接收到了第一次连接时发出的数据段怎么办呢?为了解决这个问题,对于每次通信双方都会有一个随机的开始序号。当接收到数据时,如果序号不在自己范围的内部,那么就直接把这一段数据扔掉。
拥塞控制的原因和方法
流量控制是指发送端和接收端之间,而拥塞控制指的是连接之间网络、路由器存在吞吐上限,出现分组丢失、分组延迟长的现象。
当路由器缓存达到最大值时,则会丢弃分组,导致分组丢失。当路由器接收到的速率大于路由器将数据发送到下一个节点的速率,则会出现排队时延长的现象。由于延迟长,可能会被发送端误判为超时导致大量不必要的重发,进而加剧排队延迟,形成恶性循环。
常用控制方法:
| -- | -- | |
|---|---|---|
| 方法 | 特性 | 缺点 |
| 端到端拥塞控制 | 端系统根据延迟和丢失事件(超时/冗余ACK)来推断是否有拥塞,TCP采用的方法 | 没有来自网络的显式反馈 |
| 网络辅助的拥塞控制 | 路由器提供给端系统以反馈信息 |
网络信息辅助控制:每经过一个路由器,该路由器把自己当前能提供的最大带宽与这条链路上之前的路由器的最大带宽比较,到接收端时记录的是链路上最小的路由器带宽,最后接收端返回给发送端ACK时,发送端就能够知道通信链路上允许的那个最大带宽,并依此来控制发送速率。
TCP拥塞控制
端到端的拥塞控制机制,即路由器不向主机反馈有关拥塞的信息。这使得路由器的负担较轻,也符合TCP/IP架构的“网络核心简单”的原则。
- 超时:判断为拥塞。
- 原因1:网络拥塞,导致某个路由器缓冲区没有空间了,所以把这个分组丢掉,极大概率。
- 原因2:传输中出现比特错误,导致分组在接收端被丢弃了,较小概率。
- 原因1:网络拥塞,导致某个路由器缓冲区没有空间了,所以把这个分组丢掉,极大概率。
- 收到3个冗余ACK:判断为轻微拥塞
- 已传输的某个报文段丢失了,但是仅仅算是轻微拥塞,还能够进行一定程度的传输。
- 已传输的某个报文段丢失了,但是仅仅算是轻微拥塞,还能够进行一定程度的传输。
TCP拥塞控制和流量控制的联合动作
即发送端控制已发送但未确认的量,既要在避免造成网络拥塞的前提下更大,又要不能超过接收窗口以满足流量控制要求。所以取拥塞窗口和接收端缓存中剩余buffer中的较小值。
参考博客: blog.csdn.net/pang5356/ar… 。
TCP公平性
目标:当有n个TCP会话分享一个链路带宽为R的瓶颈,则每个会话的有效带宽为R/K。
网络层的组成与功能
分为数据平面和控制平面。
| -- | -- | -- |
|---|---|---|
| 控制平面 | 规划从source到target的详细路径 | 全局功能 |
| 数据平面 | 将分组在路由器从输入端口转发到合适的输出端口 | 局部功能 |
| -- | -- | -- |
|---|---|---|
| 方式 | 转发 | 控制 |
| 传统方式 | 只基于目标IP端口号,只参照转发表 | 有路由器内置算法,在多个路由器内交互并决定 |
| SDN模式 | 基于报文头部的多个字段(字段集合的任意子集),参照流表(功能包含转发、修改、阻塞、洪流等) | 在远程的服务器中决定,并把不同的流表、动作编程给各分组交换设备 |
网络服务模型
| -- | -- |
|---|---|
| 对单个数据报 | 可靠地传输,并保证较小的延迟 |
| 对数据报流 | 保序传输、保证最小带宽、保证各分组的延迟相差小 |
网络层的连接建立
在分组传输之前,在两个主机之间,在通过一些路由器所构成的路径上建立一个网络层连接。涉及到网络核心的路由器
网络层与传输层连接服务的区别:
- 网络层的连接:在两个主机之间,涉及到路径上的路由器,有连接
- 传输层的连接:在两个进程之间,一般只体现在端系统上,面向连接
路由器结构
路由器原理参考博客: blog.csdn.net/weixin_4237… 。
由输入端口、交换结构、输出端口和选路处理器组成。
端口:每个端口既是输入端口也是输出端口,只是不能同时承担。
选路处理器:路由,运行路由选择算法/协议,生成路由表。
交换结构:转发,从输入到输出链路交换数据报,根据路由表进行分组的转发。
输入端口由三部分组成:物理层、数据链路层、分布式交换模块。
| -- | -- |
|---|---|
| 物理层 | 连接一条物理链路,把比特从物理信号转为电信号(或相反操作) |
| 数据链路层 | 把得到的数据帧进行解封装和分析,得到数据报(或封装后交给物理层) |
| 分布式交换模块 | 有一份动态更新的转发表的副本,在端口内部实现查找和转发功能,以便路由器内部的交换结构将数据报转发到合适的输出端口 |
输入(输出)端口缓存
若交换结构的速率小于输入端口的汇聚速率时,在输入端口会发生排队。为了减少丢失,于是设置了一个输入端口缓存。
当发生排队时,由于发生排队时延和缓冲区溢出,可能产生丢包。
缓冲区内的分组不是先到先传,而是取决于一个存在的调度算法,可以对高优先级的分组(实时多媒体应用的分组)优先传输。
交换结构的发展历史
- 经内存交换:早期结构,交换是在CPU的直接控制下完成的。需要通过系统总线进出一次内存,因此总转发吞吐量小于总线带宽的一半。
- 经总线交换:改版结构,输入端口通过一条共享总线将分组直接传送到输出端口,每次只能有一个分组通过总线传送。因此交换速率受总线带宽限制。
- 经交换矩阵交换: n 纵 n 横总 2n 条总线。到达输入端口的分组沿水平总线穿行,直至与所希望的输出端口的垂直总线交叉点:到达交叉点后若该条垂直总线空闲,则分组被传送到输出端口;否则,该到达的分组被阻塞,必须在输入端口排队。
网际协议
包括路由协议、IP协议和ICMP协议。
- 路由协议的主要功能是路径选择,计算出用于在网络中转发分组的转发表。
- IP协议用于规定编址规则、数据报格式以及数据处理规则。
- ICMP协议主要复杂报告数据报中的差错和对某些网络层信息请求进行响应。
例如如果一台主机要判断另一台主机是否会有响应,此时可以发送一条ICMP协议的报文俗称ping,目标主机收到之后会往回发送一条响应的ICMP报文。
数据报的格式以及分片
网络层的分组被称为数据报。
IP数据报格式: 参照 blog.csdn.net/weixin_4237… 博客。
IP数据报分为首部和数据部分两部分,首部又分为固定部分和可变部分。以下介绍固定部分组成。
- 版本:4 bit , 记录数据报是 IPv4 还是IPv6 。
- 首部长度:4 bit ,范围是( 0000 ~ 1111 ),换算成十进制后乘以 4 Byte ,得到这条数据报首部的长度。因此最小可取 0101 (因为首部至少包含固定部分,固定部分的长度就是20 Byte。
- 区分服务:8 bit ,指示期望获得哪一类型的服务。
- 总长度:16 bit ,换算成十进制后乘以 1 Byte ,得到这条数据报的总长度(首部+数据部分)。
- 标识:16 bit ,分片时,同一数据报的分片会使用同一个标识,方便接收端接收来自同一数据报的不同片。
- 标志:3 bit ,但之后后两位有用。
中间位DF为1的时候表示禁止分片,为0的时候表示允许分片。
最低位MF为1的时候表示此片后面还有其他片,为0的时候表示此为最后一片或者这没分片。 - 片偏移:13 bit ,分片后的每一片数据的起始部分在原始数据报中的 offset ,以 8 Byte 为单位,方便接收端主机进行排列组合成完整的数据报。
- TTL(time to live):8 bit ,总跳数。
- 协议:8 bit ,指示数据部分的协议,也是区分TCP和UDP的部分。
- 源地址、目标地址:各32bit。
- 可选字段:长度可变,可有可无。
- 填充:全0,把首部补成整数倍于4 Byte 的长度。
数据报分片
为什么要进行分片呢?因为因特网中并非所有链路层协议都能承载相同长度的网络层分组。例如以太网帧能够承载不超过1500字节的数据,而某些广域网链路的帧可承载不超过576字节的数据。但是在因特网中,允许数据报在从发送主机到接收主机的传送过程中经过不同的链路。因此当一个大的数据报转发到一条只能承载小数据报的链路时就需要进行分片。
示例:一个4000字节的数据报(包括了20字节的IP首部和3980字节的IP有效载荷)到达一台路由器,且必须被转发到一条MTU为1500字节的链路上。这就意味着初始数据报中的3980字节数据必须被分配为3个独立的片,其中的每个片也是一个IP数据报。
首先要知道,如果进行分组,势必要让之后的每个节点都知道哪几个分组是属于同一个原始数据报。因此通过ID号来表示原始数据报,ID号相同的分组都属于一个原始数据报。
其次,接收方如何对多个来自同个原始数据报的分组进行排序呢?用一个偏移量来解决。偏移位为0表示插入的数据开始于字节0;偏移185表示插入的数据开始于字节1480(1858=1480);偏移370表示插入的数据开始于字节2960(3708=2960)。
最后,接收方如何知道有完没完?这里通过通过标志位(fragflag)来表示数据报进行的分片,如果标志位为1,则表示后面还有数据。标志位为0表示这是最后一个分片,后面没有数据了。
总结就是,一个大的数据报在中间路由器被分为三个小的数据报,而这些小的数据报将在网络中继续转发,后续路由器将每个数据报作为一个独立的报文进行转发,直到到达接收方主机,接收方主机根据分片相关的标识符、标志位和片偏移等字段对这些报文进行重组。这些字段无论在原始较长的数据报还是分割后的各个小分组数据报中,都是存在的。都在IP数据报的头部里面。。
IP地址简单介绍
通俗理解:一栋楼可能很多间,而每一间的门牌号都是不同的,尽管门后是同一块地方。而IP地址指的就是这一个个的门而不是这栋楼。
技术理解:一个IP地址技术上是与一个接口相关联的,而不是与包括该接口的主机或路由器相关联的。路由器会有多个接口,因为路由器的任务是从链路上接收数据报并从某些其它链路转发出去,所以路由器必须拥有两条或更多链路与它连接;主机也可以有多个接口,例如笔记本通常会有无线网卡接口,也会有有线网卡的以太网接口。每个接口有一个IP地址。在因特网中设备通过IP地址进行寻址。
IP子网
IP子网是IP地址具有相同的网络号的设备接口。
IP地址为 223.1.1.1 和 223.1.1.2 的节点,他们的IP地址的高位部分相同,因此这些节点构成的网络的一部分叫做子网。而 223.1.1.1 和 223.1.1.2 构成的子网如果从网络更外部看,和 223.1.2.1 和 223.1.2.2 构成的子网又是处在同一个子网当中。子网内各主机可以在物理上相互直接到达,不通过路由器。
为什么要有子网呢?因为IPv4时代全球就有四十多亿个IP地址,倘若依据每一个独立的IP地址的广播来计算路由器的转发表,可想而知会有多难。因此把高位部分相同的IP地址划分在同一个子网内部,发送分组时发送到一级一级的子网。路由是以网络为单位来做路由信息的计算和发布的。
IP编址
IPv4里,IP地址是32比特。
网络号(NetID)是高位比特,主机号(HostID)是低位比特。
11011111 00000001 00000001 00000001 = 223.1.1.1
A类地址:8位网络号,24位主机号,地址以0开头。 0.0.0.0 ~ 127.255.255.255
B类地址:16位网络号,16位主机号,地址以10开头。 128.0.0.0 ~ 191.255.255.255
C类地址:24位网络号,8位主机号,地址以110开头。 192.0.0.0 ~ 223.255.255.255
D类地址:地址以1110开头。
E类地址:地址以1111开头。
私有IP地址:是在A、B、C三类IP地址中保留下来为企业内部网络分配地址时所使用的IP地址。私有地址主要用于在局域网中进行分配,在 Internet上是无效的。这样可以很好地隔离局域网和 Internet。私有地址在公网上是不能被识别的,必须通过NAT将内部IP地址转换成公网上可用的IP地址,从而实现内部IP地址与外部公网的通信。公有地址是在广域网内使用的地址,但在局域网中同样也可以使用,除了私有地址以外的地址都是公有地址。
子网划分
把IP地址中的主机号部分进行再划分,使得IP地址由网络号、子网号、主机号组成。注意,划分子网仅仅是把主机号再划分,并没有改变IP地址和IP地址的网络号。
什么是子网掩码呢?又是一个熟悉却不识含义的词。是因为从IP数据报首部无法看出源主机或目的主机所连接的网络是否进行了子网划分,因此引用子网源码进行区分。从子网掩码中可以看出IP地址哪些位是网络号、哪些位是主机号。
例如A类地址的前8位是网络号,后24位是主机号,那么A类的默认子网掩码就是一个“前八位是1、后24位是0”的数,即“255.0.0.0”。
再如借用3比特划分子网的B网的子网掩码为:255.255.224.0 ,即 11111111 11111111 11100000 00000000 ,其中子网号占用了三位主机号并把3位主机号变成了1,因此此时子网掩码是 255.255.224.0 。
那么如何通过一个IP地址,来确定要把这个分组转发到哪个子网呢?很简单,把分组的目的IP地址和该地址的子网掩码按位与运算,就能够得到一个只剩网络号和子网号的IP地址,主机号被全部归为0。
使用子网时的分组转发
在使用子网划分后,路由器的转发表必须包含这三个内容:目标IP地址、子网掩码、下一跳地址。
转发分组算法如下:
- 从收到的数据报的首部提取目的IP地址D。
- 先判断是否为直接交付。对路由器直接相连的网络逐个进行检查:用各网络的子网掩码和D逐位相“与”,看结果是否和相应的网络地址匹配。若匹配,则把分组进行直接交付(当然还需要把D转换成物理地址,把数据报封装成帧发出去),转发任务结束。否则就是间接交付,执行3。
- 若路由表中有目的地址为D的特定主机路由,则把数据报传送给路由表中所指明的下一跳路由器;否则,执行4。
- 对路由表中的每一行(目的网络地址,子网掩码,下一跳地址),用其中的子网掩码和D逐位相“与”,其结果为N。若N与该行的目的网络地址匹配,则把数据报传送给该行指明的下一跳路由器;否则,执行5。
- 若路由器中有一个默认路由,则把数据报传送给路由表中所指明的默认路由器;否则,执行6。
- 报告转发分组出错。
IP地址分配
首先记住主机号为全0和全1的不用。
IP地址具体怎么分配呢?即给定一个地址块,怎么进行子网划分,以及为每个子网分配地址段呢?
某单位从ISP处购买了一个IP地址块202.40.70.0/24。如果该单位有3个部门,第一个部门78台计算机,第2个和第3个部门各有48台计算机,现在我们为这3个部门划分子网,给出各部门的网络号、子网掩码和主机可分配的IP地址范围:
因为202.40.70.0/24前24位是网络号,后8比特是主机号可以用于分配。在后8比特中可以将其划分为3个子网。每个子网对应一个部门。子网划分的好处是可以进行广播流量的隔离。子网1分配的IP地址范围至少需要支持78台电脑,子网2和子网3分配的IP地址范围至少需要分别支持48台电脑。78个IP地址至少需要用7比特来表示(因为2^6是64,不够分配78台电脑)。因此可以选择用最高位为0表示子网1即前25位是网络号,后7位是主机号;最高位为1表示子网2和子网3,那么进一步怎么区分子网2和子网3呢?48个IP地址只需要6比特来表示即可,因此可以采用次高位来区别子网2和子网3。次高位为0表示子网2,次高位为1表示子网3。由此可得以下设置:
| -- | -- | -- | -- |
|---|---|---|---|
| 地址范围 | 网络号 | 子网掩码 | |
| 子网1 | 202.40.70.00000001 ~ 202.40.70.01111110 | 202.40.70.0/25 | 255.255.255.128 |
| 子网2 | 202.40.70.10000001 ~ 202.40.70.10111110 | 202.40.70.128/26 | 255.255.255.192 |
| 子网3 | 202.40.70.11000001 ~ 202.40.70.11111110 | 202.40.70.192/26 | 255.255.255.192 |
路由通告
通告的聚集是为了减少转发表计算和选择的时间。
通告的最长匹配原则是为了选择正确的下一跳。
首先多个路由器向一个逻辑上级的路由器A发出通告(我要IP地址为这些的报文)。A收到之后如果发现这些IP地址的网络号的前几位是一样的(且这几个路由器的通告加起来可以填满剩下几位的大部分可能,可以存在小空洞),就把这些通告聚集成一个通告并进行对逻辑上级的通告;如果不符合,那么就一个一个进行通告的转发。
既然有聚集,那么就存在一种情况:路由器收到的一个IP地址可以满足转发表里面的多项通告。那么此时应该匹配和转发的下一跳是哪个路由器呢?这里采用的是最长匹配原则,即哪个通告可以匹配这个IP地址的位数越多,这个通告就是更精确,那么这个IP报文就会选择这个路由器作为下一跳。
DHCP协议
我们首先要知道,如果小杜获得了一块地址,那么我可以为我名下的主机和路由器接口逐个分配IP地址。主机IP地址当然可以手动配置,但是为了方便使用的是动态主机配置协议,即DHCP。
DHCP允许一个主机在加入网络时自动获取以下信息:IP地址、子网掩码、默认网关、DNS地址。
注意,这个IP地址有一个租用期即有效期,当然可以在到时的时候renew。
这个地址可以让只拥有一定个数IP地址的组织向多于IP数的主机提供服务,因为只有接入网络才需要IP地址,而并不是所有主机都会在同一时间都加入网络。
工作过程:
- DHCP discover :当一个主机连入网络时,它需要请求IP地址。首先客户在UDP分组中向端口67发送DHCP discover报文,这个报文声明自己的存在。src是0.0.0.0,这是因为笔记本也不知道自己的IP地址。目的地址255.255.255.255是广播地址,因此会生成一个广播帧,而这个广播帧会在局域网广播。(我出现啦!)
- DHCP offer : 当DHCP discover报文被同一个局域网的DHCP服务器收到时,它会返回一个DHCP offer报文。这个报文的目的地址仍然是广播地址。DHCP offer消息中还有收到的DHCP discover报文的事务ID 号、向客户主机推荐的IP地址、网络掩码、IP地址租用期等信息。(这个给你好不好?)
- DHCP request : 当主机收到来自DHCP服务器的DHCP offer消息时,它会返回DHCP request进行IP地址的请求。(我就要这个!)
- DHCP ACK : 最后服务器用DHCP ACK消息对请求进行响应。(好。)
NAT
目的:为了实现内网与外界通信,因为外界是无法通过一个内网IP地址找到一台主机的。
NAT路由器实现过程:
- 对外出数据包,替换源地址和端口号为NAT IP地址和新的端口号,目标IP和端口不变。而远端的CS将会用NAT IP地址和新的端口号作为其目标地址。
- 然后把每个转换替换对记录在NAT转换表中。
- 对进入数据包,查找转换表,找到远端CS地址对应的那一条,替换目标IP和端口号为内网的源地址和端口号。
特点:内网中发出的数据报具有一个相同的IP地址,得到回应报文时根据中间转换路由的缓存得到目标主机是内网中的哪一台设备。
| -- | -- |
|---|---|
| 优点 | 1.内部设备没有明确的地址,对外是不可见的。 2. 不需要从ISP分配一块地址,可把一个IP地址用于所有的局域网设备。 |
| 缺点 | 1. 外网设备无法主动连接到内网机器。 2.违反了端到端的主张,即本只该处理到网络层的路由器修改了传输层的信息(端口号)。 |