网络层

网络层实现主机到主机的通信服务,在网络中的每一台主机和路由器都有一个网络层部分,是协议栈中最复杂的部分,也是最有趣的部分


要跳出现有系统的限制来思考问题,想想什么是可行的!

一个人要不断地超越自我,否则还有什么乐趣可言?!

概述

转发与路由选择

网络服务模型

虚电路

数据报网络

转发

路由器原理

路由器结构
路由器有四个组成部分

  • 输入端口:它既要执行将一条输入的物理链路与路由器相连接的物理层功能;还要执行需要与位于入链路远端的数据链路层交互的数据链路层功能;还要完成查找功能,在这里通过查询转发表决定路由器的输出端口
  • 交换结构:将输入与输出端口相连接,这种交换结构完全包含在路由器中,是路由器的网络
  • 输出端口:存储从交换结构接受的分组,并通过执行必要的链路层和物理层功能在输入链路上传输这些分组
  • 路由选择处理器:执行路由选择协议,维护路由选择表以及连接的链路状态信息,并为路由器计算转发表

路由器的转发功能总是用硬件实现,因为该功能是以纳秒时间尺度执行的,这远超过软件实现的速率,路由器的控制功能在毫秒或者秒时间尺度执行,因此用软件实现并在路由选择处理器上执行

输入端口

上面说过在这里,路由器通过转发表来查找输出端口,转发表是由路由选择处理器计算和更新的,但是转发表的一份影子副本通常被放在每个输入端口,通过独立总线(如PCI总线)复制到线路卡,这样就能在输入端口做出转发决策

概念上只要搜索转发表查找最长前缀匹配,但这种查找必须在纳秒级执行,因此除了硬件帮助还要快速查找算法

当分组确定了输出端口,就会进入交换结构。在某些设计中,如果其他输入端口的分组当前正在使用交换结构,一个分组可能会在进入时被暂时阻塞,要排队等待调度

除此之外,在输入端口还要做其他操作

  • 必须出现物理层和链路层处理??
  • 必须检查分组的版本号、检验和寿命字段,并重写后两个字段
  • 更新用于网络管理的计数器,如接受到的IP数据包的数目

最后,对于在输入端口做的处理,即查找IP地址然后发送该分组进入交换结构,我们抽象成匹配加动作的特定执行,这种抽象作用很大,而且在网络设备中无处不在

交换结构

交换可以用许多方式完成

  • 内存交换:最早的路由器就是传统的计算机,交换是由CPU的直接控制下进行,输出、输出端口就像传统OS的I/O设备一样
  • 总线交换:输入端口经一根共享总线将分组直接传送到输出端口,不需要路由处理器的干预。让输入端口为分组预先计划一个交换机内部标签,指示本地输出端口,使分组在总线上传送到输出端口。该分组能由所有输出端口收到,但是只有与该标签匹配的端口才能保存该分组。到达后,标签由输出端口去除,因为标签只用于交换机内部来跨越总线。这种方法的缺点在于总线是共享的,一次只能有一个分组能够跨越总线
  • 互联网络交换:该结构类似于井字格,由2N条总线组成的互联网络,它;连接N个输入端口和N个输出端口,交叉点通过交换结构控制器能在任何时候开启与关闭。因此纵横式网络能够并行转发多个分组,但是对于有相同输出端口的分组,依旧有阻塞、排队的现象

输出端口

处理取出存放在输出端口内存中的分组并将其发送给输出链路上

排队

排队的位置取决于流量负载、交换结构的相对速率和线路速率。当队列增大时,就会出现缓存空间耗尽的情况,此时就会出现丢包

假设所有分组都发向相同的输出端口,这时候输出端口的队列就会无限增大。那路由器需要多少缓存来吸收流量负载的波动?一种经验方法是和平均往返时延和链路容量之间的函数决定

当输出端口出现排队,就需要分组调度程序来决定选取一个分组来发送。这种选择的原则有先来先服务调度(FCFS)、加权公平排队(WFQ)

如果实在没有足够内存来缓冲一个分组,就需要策略来决定丢掉分组。一种是丢弃到达的分组(弃尾);另一种就是删除一个或者多个分组,来为新的分组腾出空间

在缓冲填满前便丢弃分组,以便向发送方提供一个拥塞信号,这种策略统称为主动队列管理(AQM)算法。其中随机早期检测(RED)是一种广泛应用的AQM算法。在RED算法中,为输出队列维护一个加权平均值,如果队列长度小于最小阈值,则接纳分组,如果大于最大阈值,则丢弃分组,如果介于最大阈值和最小阈值之间,则以某种概率被丢弃,该概率是平均队列长度、最大阈值、最小阈值之间的函数

当然输入端口也会出现分组排队现象。 这时候会出现一种叫做线路前端阻塞现象,即在一个输入队列中排队的分组必须等待通过交换结构发送,即使输出端口使空闲的,因为他被位于线路前部的另一个分组阻塞

网际协议

因特网编制和转发是网际协议(IP)的重要组件,目前有两个版本的IP在使用,IPv4和IPv6

因特网的网络层有三个组件

  • IP协议
  • 路由选择部分:决定数据包从源到目的地流经的路径
  • ICMP协议:报告数据包中的差错和对某些网络层信息请求进行相应的设施

路由选择

路由选择算法,是网络层为从发送方到接收方的分组确定所采取的路径的策略

经验总结

今天用go部署一个后端api是出现了一个网络上的问题,具体描述如下:通过go的log.Fatal(http.ListenAndServe("localhost:8000",ns))创建一个服务器,在本地都能顺利访问,当相同的代码部署到服务器上,外网通过ip地址去访问就会出现错误,后来发现需要改成log.Fatal(http.ListenAndServe("0.0.0.0:8000",ns))才能顺利访问

127.0.0.1是本地环回地址,专供自己访问自己,速度快(不用经过整个协议栈),永远都不能出现在主机外部的网络中,所以只适合用在开发环境。localhost只是127.0.0.1 的别名。

0.0.0.0有几个不同的含义,不过当告诉服务器监听了0.0.0.0,意味着监听每一个可用的网络接口,从服务器进程的角度来看IP地址为127.0.0.1的环回适配器看起来就像机器上的任何其他网络适配器一样,因此被告知监听0.0.0.0的服务器也将接受该接口上的连接。
因此在实际应用中,一般我们在服务端绑定端口的时候可以选择绑定到0.0.0.0,这样外网的服务访问就可以通过主机的多个ip地址访问我的服务。