网络知识点

基础知识

五层协议

  • 应用层: 为特定的应用传输数据. HTTP, SMTP, DNS
  • 传输层: 实现进程到进程之间的通信. TCP/UDP 协议
  • 网络层: 实现主机到主机之间的通信. IP, ICMP, ARP, OSPF协议.
  • 链路层: 为同一链路的主机提供服务. PPP协议, MAC协议
  • 物理层: 在传输媒体上传输比特流, 尽可能为数据链路层屏蔽不同通信设备的差异. RJ45, IEEE802.3协议.

MTU和路径MTU

MTU: 链路层数据帧能携带的最大的数据量(不包含链路层头部), 例如以太网限制有效载荷为1500字节.
如果ip需要发送一个数据报, 并且这个数据报比链路层MTU要大, 则ip通过分片将数据包分解为多个较小的ip数据报,
使每个分片不超过MTU. 这导致ip头部多次出现, 降低了有效数据占的比例.

路径MTU: 两台主机跨越多个网络通信时, 每个链路可能有不同大小的MTU, 其中最小的称为路径MTU.

TCP

TCP特点

面向连接, 提供可靠通信, 支持全双工, 面向字节流, 点对点通信.

TCP通过确认和超时重传, 数据分片和排序, 流量控制, 拥塞控制, 数据校验实现可靠传输.

一个TCP套接字是由一个四元组来标识的: <源地址, 源端口号, 目的地址, 目的端口号>.

TCP握手阶段的SYN标志是占据一个序列号的, 而消耗了序列号就意味着SYN也是数据, 就会被可靠传输,
即对方会有ACK, 会有超时重传等措施. 而不消耗序列号的ACK不会被保证可靠传输.

TCP处理流程

  • 校验: 包含头部信息, 数据部分, 伪头部(源地址, 目的地址, 0, 协议号, TCP报文长度, 总计12字节).
    如果校验出错, 数据包被丢弃, 接收方可能会回复一个对之前已接受数据包的 ack, 以通知发送方重传此数据包.

TCP流量控制

为了使发送方的发送速率与接收方的处理速率匹配, 通过维护接收窗口来实现, 接收窗口表明了接收方可用的缓存空间大小(字节数).
TCP头部的16位用于向另一方表明自身接口窗口的大小.
发送方可发送的最大序列号值为: 当前的ACK序列号+窗口大小.

UDP不支持流量控制, 当发送方发送数据过快时, 数据包会溢出, 导致数据包丢失.

  • 滑动窗口: 累积确认, 回退N帧.

发送方窗口可以分为四个部分, 其中已发送未确认部分+即将发送部分就是对方宣告的窗口大小.

  • 已发送, 已确认
  • 已发送, 未确认
  • 即将发送
  • 不能发送

接收方窗口分为3个部分, 收到第一部分的数据包是重复的, 会被丢弃; 收到第三部分的数据包查出处理范围,
同样被丢弃. 只有收到第二部分的才会被保存下来, 但是只有收到左边界的数据包, 窗口才会右移.

  • 已接收并确认
  • 接收后将会保存
  • 不能接收

TCP拥塞控制

使发送方的发送速度与网络情况匹配, 这是对发送方发送速度的限制.
发送方通过超时, ack来感知网络的变化, 通过窗口大小来控制发送速度.

  • 慢启动

当一个新的TCP连接建立或超时时, 执行慢启动. 慢启动指数地增长窗口大小, 每收到一个 ack 就将窗口乘以 2.
如果发生了超时, 将阈值设为当前窗口的一半, 窗口大小设为1, TCP重新进入慢启动状态.
如果窗口大于等于阈值, TCP进入拥塞避免状态.
如果收到 3 个重复的 ack, 表明发生了丢包, 进入快速恢复阶段.

连接建立时的窗口大小可以设定.

  • 拥塞避免

线性地增长窗口, 每收到一个 ack 就将窗口加 1.
如果发生了超时, 将阈值设为当前窗口的一半, 窗口大小设为1, TCP重新进入慢启动状态.
如果收到 3 个重复的 ack, 表明发生了丢包, 进入快速恢复阶段.

  • 快速恢复

先将阈值设为当前窗口的一半, 再将窗口设为 阈值 + 3MSS, 然后重传丢失的数据包.
如果收到了期望的 ack, 就进入*
拥塞避免状态, 继续线性地增加窗口大小.
如果发生了超时, 就进入
慢启动**状态.

旧的实现采用Tahoe算法, 当遇到丢包时, 无论是超时还是重复ACK导致的, 到进入慢启动状态.
后来改为Reno算法, 区分了这两种丢包, 分别进入慢启动和快速恢复状态.

更新的实现采用了NewReno算法, Reno算法在有多个数据包发生丢失时的表现不好.
在第一次收到ACK后, 退出快速恢复, 然后又接收到重复ACK, 再次进行快速恢复. 这个过程会重复多次, 降低了效率.
NewReno算法记录传输窗口的最高序列号(即
恢复点
), 当发生拥塞避免时, 记录之前发送数据包的最高序列号,
只有当接收到的序列号不小于恢复点的ACK, 才会停止快速恢复阶段.

更复杂的算法是选择确认(SACK), 利用TCP头部的可选项来记录丢失的序列号, 并且要在握手阶段指出是否支持SACK.
利用ack数据包前20字节的ACK序列号和option部分的序列号, 就可以确定丢失的数据.
option部分的序列号是成对出现的, 表示了已接受到数据的范围, 可以有多个序列对.
因为序列对占8个字节, option部分不超过40字节, 因此最多有4个序列对, 实际中由于其他选项占用一般最多只有3对.
设序列对为 (seq1, seq2), (seq3, seq4), (seq5, seq6), ack序列号为 seq0. 那么缺失的序列为: [seq0, seq1), [seq2, seq3), [seq4, seq5)[seq0,seq1),[seq2,seq3),[seq4,seq5).
有一点需要注意, 为了防止之前的SACK丢失, SACK会尽量包含之前的(最近的)SACK信息.

 累积确认

主要用于交互式数据传输的情况.(如ssh)

当收到数据时, 并不立即回复 ack, 而是等待一段时间, 尽可能使得 ack 能和这个方向上的数据一起发送.

Nagle算法

是为了处理这样的情况: 大量的小数据包有效数据占比太少, 浪费了带宽. 例如用于交互式数据传输的情况(如ssh)

规定当存在没有被确认的数据包时, 过小的数据包不能被发送, 直到所有的数据都被确认.
并且确认之后, 需要将这些小数据整合到一个数据包发送.

三次握手

三次握手的过程

  1. 客户端发送 syn 数据包, 设置序列号(n).(由于设置了 SYN 字段, 虽然数据项为空, 仍然消耗一个序列号, 所以服务端的 ack 会加一)
  2. 服务端接收到 syn 数据包后, 发送 syn&ack 数据包给客户端, 设置序列号(m), ack序列号(n+1).
  3. 客户端收到 syn&ack 数据包后, 发送 ack 数据包给服务端, 设置序列号(n+1), ack序列号(m+1).

三次握手为了解决哪些问题

  • 交换双方的序列号.
  • 当客户端的 syn 数据包长经过很长时间才到达服务端, 而此时客户端认为此数据包丢失时, 服务器会响应此数据包,
    客户端需要第三次握手来正确处理他. 例如发送RST. 如果客户端置之不理, 会导致服务端长期处于等待/重传状态.

四次挥手

四次挥手的过程

对于主动关闭一方:

  1. 发送 FIN, 进入 FIN_WAIT_1.
  2. 收到 ACK, 进入 FIN_WAIT_2.
  3. 收到 FIN, 回复 ACK, 进入 TIME_WAIT/2MSL.
  4. 2MSL时间之后, 进入 CLOSED.

对于被动关闭一方:

  1. 收到 FIN, 回复 ACK, 进入 CLOSE_WAIT.
  2. 发送 FIN, 进入 LAST_ACK.
  3. 收到 ACK, 进入 CLOSED.

四次挥手的原因

TCP是全双工模式, 两次挥手只会释放一个方向的连接, 释放双向的连接需要四次. 当一方释放连接时,
另一方可能还有数据未传输完, 因此两次连接释放不能合并.

2MSL

当执行主动关闭的一方收到被动关闭一方的 FIN 数据包时, 回复 ACK 数据包, 就进入 TIME_WAIT 状态,
并至少持续 2MSL 时间. (MSL 表示报文在网络中最长的生存时间)

在 TIME-WAIT 状态, 当:

  • 接收到 FIN 数据包时, 会再次回复 ACK.
  • 期间端口号不能被再次使用.

这是为了解决两种异常情况:

  • 防止被动关闭的一方没有收到回复的ack, 这样 FIN 就会再次发送, 主动关闭方收到后再次回复 ack,
    并重新进入 TIME_WAIT 状态.
  • 保证此次连接的所有数据包都消失或被处理, 不会出现在新的连接中. 如果过快建立新的连接,
    可能本次连接的数据包因为延迟, 出现在新的连接之中.

TCP 中的 Timer

注意一点, 下面说得timer并不是超时超时重传中用到的timer. 而且有的timer定义的是次数, 但是实际上协议栈并不仅仅只考虑次数,
会结合时间来看.

  1. connection-establishment timer

    在建立tcp连接时起作用, 有两个:

    • tcp_syn_retries: client发送完 SYN 后, 进入 SYN_SENT 状态, 等待服务端回复 SYN+ACK.

    • tcp_synack_retries: server 收到 SYN, 回复完 SYN+ACK 后, 进入 SYN_RCVD 状态, 等待client的 ACK.

      在上面的两个等待中, 如果发生超时, 就会重传数据包. 但是不能无限制的重传, 因此分别定义了 tcp_syn_retries 和 tcp_synack_retries,
      二者表示重传的次数, 间接定义了最长的等待时间.

  2. retransmission timer

    三次握手成功后, 连接建立, 客户端就可以发送数据包, 再等待服务端的ACK. 如果在指定时间内没有收到ACK,
    就会重传, 直到重传了指定的次数才会放弃. 这里存在两个timer, 都是重传次数:

    • tcp_retries1: 如果重传超过这个值, 就会更新路由缓存, 然后继续重传.
    • tcp_retries2: 如果重传超过这个值, 直接终止重传.
  3. delayed ack timer

    一方收到数据包后, 可以等待一定时间, 等其他数据包达到后, 一起返回ACK. 这段等待时间为 delayed ack timer,
    一般最长为 200ms.

  4. persist timer

    设想这样的情况: 当server缓存已满, 就会通知client自身窗口为0, 这导致client停止发送数据.
    当server出现空余空间后, 就需要通知client新的窗口大小, 但是这个通知不会携带任何数据,
    所以client不会回复ack, 因此即使这个数据包丢失了server也不会感知到(ACKs are not acknowledged, only data is acknowledged).
    如果此通告client没有接收到, 也就不会继续发送数据包. 因此需要一种机制来解决此问题:

    client知道server窗口为0后, 当有数据要发送时, 虽然知道不应该发送数据, 也会在一段时间后尝试发送一个字节.
    这段时间就是 persist timer.

  5. keepalive timer

    当启用tcp socket的SO_KEEPALIVE option时, 即使双方没有数据发送, 也会保持连接. 保持连接的方式是发送probe segment.
    当连接经过一段时间(tcp_keepalive_time)没有数据包传送后, tcp就会主动发送 probe segment,
    强制对方回应. 并且每隔一段时间(tcp_keepalive_intvl)就会发送一个probe segment,
    如果对方没有回应, 在连续发送了一定数量(tcp_keepalive_probes)后, 主机就会放弃, 并终止连接.

  6. fin_wait_2 timer

    client主动终止连接(发送FIN), 并收到ACK后, 就进入 fin_wait_2状态. 此时不能继续发送数据,
    如果server一直不发送FIN, client就会一直处于此状态, 导致资源无法释放. 因此定义了 tcp_fin_timeout(单位是秒),
    当处于fin_wait_2的时间超过这个时间时, 就会终止连接.

  7. time_wait timer

    即2MSL, 其作用是为了回复的ack丢失时, 能收到重传的FIN并继续返回ack, 另一个是保证当前连接的数据包完全消失.

UDP

UDP特点

无连接(没有握手过程), 尽最大努力交付, 面向报文, 首部只有8个字节, 支持多对多通信.

一个UDP套接字是由一个二元组来标识的: <目的地址, 目的端口号>.

UDP提供端到端的校验, 接收方会根据头部的检验和判断数据包是否发生错误, 但是不能恢复错误, 只能交由上层应用来处理.
检验和覆盖了UDP头部, UDP数据, 伪头部, 运算单位是2字节(16位). 伪头部指的是:

  • 源地址ip(4字节)
  • 目的地址ip(4字节)
  • 0(1字节), 协议号(1字节), UDP长度(2字节)

之所以加上伪头部是为了检验数据是否到达了正确的目的地.

UDP处理流程

IP

IP数据包头部包含20个字节加上可选部分.

  • 校验和: 只包含IP数据包的头部. 每台路由器收到ip数据包后都会利用检验和进行校验, 如果出错, 就会将数据包丢弃.
    否则会重新计算校验和. 因为IP头部信息是在不断变化的, 例如TTL.

  • ip分片: 上层的数据报过大时, 会进行分片, 以满足接口的MTU限制. ip分片直到到达运输层目的地时才会在网络层重组.
    如果一个报文的分片丢失, 整个报文会被丢弃, 不会交给运输层. 之所以在目的地才重组, 原因有二:

    • 在网络中不进行重组能减轻路由转发的负担.
    • 同一数据报的不同分片可能经由不同的路由到达目的地, 因此在中间重组是不可能的.

路由协议-内部网关协议(用于AS内部)

RIP协议

RIP协议使用两个子网之间经过的子网数来作为距离, 相邻子网距离为1, 称为跳数.

相邻路由器交换路由选择信息, 其中包含了路由器自身已知的到其他路由器的跳数.
路由器根据接收到的路由选择信息更新转发表. 转发表包含目的子网, 下一跳路由, 到目的子网的跳数.

OSPF协议

工作在网络层, 依赖IP.

和全局的所有路由器交换信息, 用得到的信息构建链路状态数据库, 用Dijkstra算法计算最短路径, 生成路由表.
详细过程为:

  1. 路由器和直接相连的路由器交互, 发送Hello报文, 建立邻居关系.
  2. 路由器根据和直接相连的路由器间的链路构建链路状态广播(LSA), LSA记录了所有相邻的路由器及其表示, 链路类型, 带宽等.
  3. 路由器将自己的LSA发送给所有邻居, 接收到LSA的路由器也会将LSA发送给其他邻居节点.(组播)
    最终一个区域中的所有路由器都可以得到区域的完整拓扑, 并基于此来构建链路状态数据库.
  4. 根据链路状态数据库, 路由器采用Dijkstra算法计算出一棵以自己为根的最短路径树, 并生成路由表.

OSPF运行在一个自治域(AS)中, 并允许将一个自治域划分为多个区域, 其中必须有一个是骨干域,
其他的称为非骨干域, 每个非骨干域都必须与骨干域相连(直接或间接).
根据路由器接口所在区域的不同, 一个路由器可以有三种角色.

  • 区域内部路由器: 所有接口都在区域之中;
  • 区域边界路由器(ABR): 用于连接非骨干区域和骨干区域, 即有的接口处于非骨干区域, 有的接口处于骨干区域,
    前者可以有多个处于不同非骨干区域的.
  • 自治域边界路由器(ASBR): 用于连接当前AS与其他AS.

IS-IS协议

工作在网络层.

与OSPF的不同点:

  • 虽然将AS划分为多个区域, 但是区域的边界在链路, OSPF的区域边界在区域边界路由器(ABR).
    进而OSPF中每条链路只属于一个区域, 而IS-IS中每台路由器只属于一个区域.
  • 在区域内采用最短路径优先来计算路径, 在区域间用距离向量来计算路径.

IS-IS协议同样将AS划分为多个区域, 区域之间通过链路(OSPF是路由器)相连.
IS-IS中路由器分为三种:

  • level 1 路由器: 作用于区域内, 没有直接连接到其他区域的链路. 负责收集区域内的路径信息.
  • level 1-2 路由器: 有直接连接到其他区域的链路, 负责收集区域间的路径信息.
  • level 2 路由器: 作用于区域外, 负责收集区域内和区域间的路径信息. 类似OSPF中的ABR.(?)

路由协议-外部网关协议(用于AS之间)

BGP协议

BGP路由基于前缀, 采用路由聚合策略, AS之间通过网关路由器交换信息.

路由转发过程

  • 路由表包含下面的信息: 目的ip, 子网掩码, 下一条ip, 标志, 接口等. 使用最长前缀匹配算法来寻找下一跳.

  • 最长前缀匹配算法: 在表中搜索所有条目, 记录掩码运算后匹配的条目, 并选择最匹配(即掩码最长)的条目进行转发.
    如果不存在匹配条目, 就返回ICMP报文, 指明"主机不可达". 存在有多个最匹配条目的情况, 此时可以直接选择第一个,
    也可以利用此来实现负载均衡, 拆分流量等.

DHCP协议

使得主机可以自动获取ip地址. 步骤如下:

  1. DHCP服务器发现: 新到主机广播DHCP发现报文(ip数据包), 并且设置源地址为 0.0.0.0, 并设置 xid(标记此次会话).
  2. DHCP服务器提供: 收到DHCP发现报文的DHCP服务器会广播回复DHCP提供报文, 其中包含对应 xid,
    提供给客户的ip地址, 子网掩码, ip地址租用期.
  3. DHCP请求: 新到的主机从若干个DHCP提供报文提供的ip地址中挑选一个, 并对该DHCP服务器发送一个DHCP请求报文,
    回显配置参数.
  4. DHCP ACK: 服务器用DHCP ACK报文对请求报文进行响应, 证实客户要求的参数.

客户一旦收到 ACK, 交互就完成了. 并且还有机制使得用户可以延长租约.

NAT协议

路由器保存一张NAT转换表, 记录局域网客户 ip:port 到广域网的 ip:port 的映射, 对向外的报文替换源地址和端口,
对向内的报文替换目的地址和端口. 注意这还需要重新计算校验码.

ICMP协议

建立在IP协议之上.

ping程序基于ICMP协议, 探测方发送一个 ICMP 请求数据包, 目的端如果没有屏蔽ICMP报文, 就会回复一个ICMP应答数据包.

traceroute基于TTL的规则, 可以采用ICMP实现, 也可以采用UDP实现. 下面是基于UDP的实现介绍.
首先设置TTL=1(在IP协议的头部), 这样到第一跳时, TTL减一之后就为0, 路由器就会返回不可达错误.
其后不断使TTL加 1, 直到到达指定目的地. 这样就能得到主机之间的路径.
并且, 程序使用的端口号大于30000, 到达目的主机后, 由于不存在这个端口, 同样会产生不可达错误,
并返回ICMP不可达给源主机. 这样源主机就知道到达了目的主机.
在基于ICMP的实现中中间路径的获取同样基于TTL的原理, 确认到达目的则是依据目的的ICMP回复.

HTTP协议

特点

http是无状态协议, 不保存关于客户的任何信息.

可以采用持续连接和非持续连接两种方式. http默认采用带流水线的持续连接.

  • 持续连接: 每一次http请求/响应都经过相同的tcp连接. 一般如果一条tcp连接经过一定时间(可配置)仍未使用,
    http服务器就会关闭该链接.
  • 非持续连接: 每一次http请求/响应经过不同的tcp连接.

http的方法:

  • get: 用于获取信息, 是安全, 幂等的. 即不会对修改数据, 重复多次得到的结果相同. 幂等.
  • head: 用于向服务请求某项资源, 服务器会按照get来处理, 但是不返回资源内容, 用户查看服务器性能. 幂等.
  • post: 向服务器提交数据, 会导致在服务器上创建/修改资源. 非幂等.
  • put: 向服务器提交数据, 如果已存在就会覆盖原有数据. 幂等.
  • delete: 请求删除服务器的资源, 不存在则会忽略请求. 幂等.
  • option: 查看指定资源支持的方法(如get, delete等), 用于检查客户端是否具有某项权限. 常用于测试服务器.
  • trace: 请求服务器回显收到的请求信息, 用于测试服务器.

下面介绍 post 和 put 的区别. 二者相同点是都需要指定一个 URI, 包含一个资源实体, 用于向服务端提交资源.
对于 post, URI被作为目录, 资源会被放置在该目录下(要求目录已经存在, 否则会返回错误), 资源的名字由服务端决定.
对于 put, URI 就是资源在服务端的完整路径.
因此, 当多次调用同一 post 方法时, 同一资源会在同一目录下保存多份, 每个资源被分配不同的名字, 因此 post 不是幂等的.
而多次调用同一 put 时, 新的请求的资源实体会覆盖已保存资源(虽然两个资源是相同的). 因此 put 是幂等的.

条件Get: 用于节省带宽, 降低负载. 用户发起get请求时, 发现本地有资源的缓存, 就设置 If-Modified-Since 字段,
后面指明时间, 如果服务器发现该时间之后对应资源没有改变, 就告知请求者, 并且不返回资源, 请求者就可以直接加载本地的资源.

DNS协议

dns协议的作用:

  • 域名解析
  • 主机别名
  • 邮件服务器别名
  • 负载均衡

dns服务器层次:

  • 根域名服务器
  • 顶级域服务器
  • 权威dns服务器
  • 本地dns服务器

dns 解析过程分为递归查询和迭代查询两种, 实际中是二者结合使用, 从终端用户看来是递归查询,
而根域名服务器和顶级域服务器都是迭代查询.

  • 递归查询: 当dns服务器无法获得ip时, 将请求转发到下一级, 再将下一级的请求转发给请求者.
  • 迭代查询: 由dns服务器先向根域名服务器发起查询, 根据回复, dns服务器再向下一级dns服务器发起查询, 直到获得ip.

本地dns服务器可以缓存常用主机名到ip的映射, 以加快dns解析. 但是缓存不能太长, 因为 dns 的映射不是永久的.

在浏览器中输入URL时的解析过程:

  1. 浏览器检查自身的DNS缓存, 没有则调用对应接***由操作系统进行解析.
  2. 操作系统先检查hosts文件是否有该映射, 有则返回.
  3. 向本地指定的dns服务器发起查询, 等待返回.
  4. 本地dns服务器检查缓存和本地记录, 如果没有就进行递归查询.

HTTPS协议

握手过程:

  1. Client Hello: 客户端向服务器发送消息. 其中包含一个客户端生成的随机数(val1).
  2. Server Hello: 服务器相应客户端的请求. 其中包含一个服务器生成的随机数(val2)和服务器的证书.
  3. 客户端请求: 客户端验证证书之后, 从证书中取出服务器的公钥, 并回复服务器.
    其中包含一个用公钥加密过的随机数(val3), 并通知服务端握手结束.
  4. 服务器回应: 服务器通过私钥解密随机数(val3), 并用三个随机数生成一个对称秘钥, 之后的数据都会有此密钥加密,
    并通知握手结束.(此时客户端也知道了三个随机数, 也就可以生成对称秘钥)

Cookie和Session

用于识别用户的身份,Cookie保存在客户端,Session保存在服务器端。

ARP协议

用于发现子网中主机的MAC地址. 过程为:

  • 主机广播请求指定 ip 的 mac 地址, 该请求被封装为一个链路层数据帧.
  • 子网上的主机收到后, 检查自身ip地址是否等于请求中的ip地址, 若等于, 就向请求主机发送回复.
  • 主机收到回复后, 更新arp表.

常见问题

访问一个网址的过程

  1. dns解析.
  2. 发起TCP连接.
  3. 向指定服务器发起HTTP请求. 服务器可能会进行反向代理, 将请求转发到其他服务器进行处理.
  4. 浏览器获取到返回结果后, 进行渲染. 如果是非持续连接, 就会关闭TCP连接.
  5. 某些资源可能需要再次发起HTTP请求, 过程同上.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值