计算机网络 速通版

Base

TCP/IP 网络模型

应用层：负责向用户提供一组应用程序。

HTTP、FTP、Telnet、DNS、SMTP 等。应用层工作在用户态。

传输层：负责端到端的通信。

TCP：流量控制、超时重传、拥塞控制等。/UDP

MSS（最大分段大小） -> TCP 段（TCP Segment）

网络层：负责网络包的封装、分片、路由、转发。

IP 协议：寻址、路由。/ICMP

MTU（最大传输单元） -> 分片

链路层：负责网络包在物理网络中的传输，比如网络包的封帧、MAC 寻址、差错检测，以及通过网卡传输网络帧等。/ARP

OSI 七层网络模型

应用层，负责给应用程序提供统一的接口；

表示层，负责把数据转换成兼容另一个系统能识别的格式；

会话层，负责建立、管理和终止表示层实体之间的通信会话；

传输层，负责端到端的数据传输；

网络层，负责数据的路由、转发、分片；

数据链路层，负责数据的封帧和差错检测，以及 MAC 寻址；

物理层，负责在物理网络中传输数据帧；

从 url 到网页显示

解析 URL -> web 服务器和文件名

生成 HTTP 请求

DNS 域名解析

TCP 三次握手建立连接

TCP 报文生成

IP 报文生成 -> IP 地址负责远程定位

MAC 报文生成（使用 ARP 查询 MAC 地址） -> MAC 地址负责两点传输

网卡，在开头添加报头和起始帧分界符，在末尾添加用于检测错误的帧校验序列（FCS），数字信息 -> 电信号

交换机（二层网络设备），查交换机的 MAC 地址表（MAC - 端口），没有就转发到所有端口

路由器（三层网络设备），路由表查 IP（路由匹配），ARP 查 MAC。

到达服务器，解析数据包，发送 HTTP 响应

客户端收到 HTTP 响应，渲染页面

TCP 四次挥手断开连接

转发过程中，源 IP 地址和目标 IP 地址不变，源 MAC 和目标 MAC 发生变化。

总体来说分为以下几个步骤:

在浏览器中输入指定网页的 URL。

浏览器通过 DNS 协议，获取域名对应的 IP 地址。

浏览器根据 IP 地址和端口号，向目标服务器发起一个 TCP 连接请求。

浏览器在 TCP 连接上，向服务器发送一个 HTTP 请求报文，请求获取网页的内容。

服务器收到 HTTP 请求报文后，处理请求，并返回 HTTP 响应报文给浏览器。

浏览器收到 HTTP 响应报文后，解析响应体中的 HTML 代码，渲染网页的结构和样式，同时根据 HTML 中的其他资源的 URL（如图片、CSS、JS 等），再次发起 HTTP 请求，获取这些资源的内容，直到网页完全加载显示。

浏览器在不需要和服务器通信时，可以主动关闭 TCP 连接，或者等待服务器的关闭请求。

HTTP_Interview

HTTP 是超文本传输协议，也就是HyperText Transfer Protocol。

什么是协议

协议 (protocol) 定义了在两个或多个通信实体之间交换的报文的格式和顺序，以及报文发送和 / 或接收一条报文或其他事件所采取的动作 。

它使用计算机能够理解的语言确立了一种计算机之间交流通信的规范（两个以上的参与者），以及相关的各种控制和错误处理方式（行为约定和规范）。

HTTP 的状态码

1xx：表示一个提示性响应

101 表示将切换协议，常见于 WebSocket 连接；

2xx：表示一个成功的响应

「200 OK」表示成功

「204 No Content」表示响应没有 body 数据

「206 Partial Content」表示只发送了部分内容；

3xx：表示一个重定向的响应

「301 Moved Permanently」表示永久重定向

「302 Found」表示临时重定向

303 表示客户端应该按指定路径重新发送请求

「304 Not Modified」表示资源未修改，重定向至缓存（缓存重定向）；

4xx：表示一个因为客户端问题导致的错误响应

「400 Bad Request」表示客户端请求的报文有错误

「403 Forbidden」表示服务器禁止访问资源

「404 Not Found」表示指定的路径不存在；

5xx：表示一个因为服务器问题导致的错误响应：

「500 Internal Server Error」表示服务器内部故障

「501 Not Implemented」表示客户端请求的功能还不支持

「502 Bad Gateway」表示服务器自身工作正常，访问后端服务器发生了错误

「503 Service Unavailable」表示服务器很忙暂时无法响应。

HTTP 的常见字段

HTTP 请求的格式是固定的，它由 HTTP Header 和 HTTP Body 两部分构成。第一行总是请求方法 路径 HTTP版本，例如，GET / HTTP/1.1表示使用GET请求，路径是/，版本是HTTP/1.1。

后续的每一行都是固定的Header: Value格式，我们称为 HTTP Header，服务器依靠某些特定的 Header 来识别客户端请求，例如：

Host：表示请求的域名，因为一台服务器上可能有多个网站，因此有必要依靠 Host 来识别请求是发给哪个网站的；

User-Agent：表示客户端自身标识信息，不同的浏览器有不同的标识，服务器依靠 User-Agent 判断客户端类型是 IE 还是 Chrome，是 Firefox 还是一个 Python 爬虫；

Accept：表示客户端能处理的 HTTP 响应格式，*/*表示任意格式，text/*表示任意文本，image/png表示 PNG 格式的图片；

Accept-Language：表示客户端接收的语言，多种语言按优先级排序，服务器依靠该字段给用户返回特定语言的网页版本。

如果是GET请求，那么该 HTTP 请求只有 HTTP Header，没有 HTTP Body。如果是POST请求，那么该 HTTP 请求带有 Body，以一个空行分隔。

POST请求通常要设置Content-Type表示 Body 的类型，Content-Length表示 Body 的长度，这样服务器就可以根据请求的 Header 和 Body 做出正确的响应。

HTTP 响应也是由 Header 和 Body 两部分组成。响应的第一行总是HTTP版本 响应代码 响应说明，例如，HTTP/1.1 200 OK表示版本是HTTP/1.1，响应代码是200，响应说明是OK。客户端只依赖响应代码判断 HTTP 响应是否成功。HTTP 有固定的响应代码。

HTTP 协议通过设置回车符、换行符作为 HTTP header 的边界，通过 Content-Length 字段作为 HTTP body 的边界，这两个方式都是为了解决 “粘包” 的问题

其他字段：

Connection：最常用于客户端要求服务器使用「HTTP 长连接」机制，以便其他请求复用。

Content-Encoding：说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式。

GET 与 POST

GET 的语义是从服务器获取指定的资源。GET 请求的参数位置一般是写在 URL 中，URL 规定只能支持 ASCII，所以 GET 请求的参数只允许 ASCII 字符，而且浏览器会对 URL 的长度有限制（HTTP 协议本身对 URL 长度并没有做任何规定）。

POST 的语义是根据请求负荷（报文 body）对指定的资源做出处理。POST 请求携带数据的位置一般是写在报文 body 中，body 中的数据可以是任意格式的数据，只要客户端与服务端协商好即可，而且浏览器不会对 body 大小做限制。

在 HTTP 协议里，所谓的「安全」是指请求方法不会「破坏」服务器上的资源。

所谓的「幂等」，意思是多次执行相同的操作，结果都是「相同」的。

所以GET 方法安全且幂等，因为它是「只读」操作，可被缓存；POST 方法不安全也不幂等，因为它会修改服务器上的资源，大都不可缓存。

HTTP 缓存

强制缓存：只要浏览器判断缓存没有过期，则直接使用浏览器的本地缓存，决定是否使用缓存的主动性在于浏览器这边。

Cache-Control，是一个相对时间；

Expires，是一个绝对时间；

协商缓存：与服务端协商之后，通过协商结果来判断是否使用本地缓存。HTTP 200 OK/ HTTP 304

基于唯一标识实现：响应头部中 Etag（唯一标识响应资源）和请求头部中的 If-None-Match；

基于时间实现：响应头部中的 Last-Modified和请求头部中的 If-Modified-Since；

注意，协商缓存这两个字段都需要配合强制缓存中 Cache-Control 字段来使用，只有在未能命中强制缓存的时候，才能发起带有协商缓存字段的请求。

HTTP 特性（HTTP/1.1）

HTTP 优缺点

HTTP 的优点是「简单、灵活和易于扩展、应用广泛和跨平台」。

HTTP 的缺点是「无状态、明文传输」，（明文传输 + 无法验证报文完整性） -> 「不安全」

HTTP 性能

HTTP 协议是基于 TCP/IP，并且使用了「请求 - 应答」的通信模式：

长连接：只要任意一端没有明确提出断开连接，则保持 TCP 连接状态，减少了 TCP 连接的重复建立和断开所造成的额外开销，减轻了服务器端的负载。

管道（pipeline）网络传输：同一个 TCP 连接，客户端发送请求后，不必等待收到响应，就可以发送下一个请求，减少整体的响应时间。但是服务器必须按照接收请求的顺序发送对这些管道化请求的响应。

队头阻塞：如果服务端在处理 A 请求时耗时比较长，那么后续的请求的处理都会被阻塞住，这称为「队头堵塞」。HTTP/1.1 管道解决了请求的队头阻塞，但是没有解决响应的队头阻塞。

HTTP/1.1 的性能一般，后续的 HTTP/2 和 HTTP/3 就是在优化 HTTP 的性能。

HTTP 与 HTTPS

建立连接时候：https 比 http 多了 TLS 的握手过程；

传输内容的时候：https 会把数据进行加密，通常是对称加密数据；

HTTP 与 HTTPS 的区别

安全

建立连接

默认端口

URL 前缀

证书

HTTPS 解决的 HTTP 的安全问题

HTTPS 在 HTTP 与 TCP 层之间加入了 SSL/TLS 协议

窃听风险 -> 信息加密 -> 混合加密

篡改风险 -> 校验机制 -> 摘要算法 + 数字签名

可以通过哈希算法来保证消息的完整性；

可以通过数字签名来保证消息的来源可靠性（能确认消息是由持有私钥的一方发送的）；

冒充风险 -> 身份证书 -> 把服务器公钥放到数字证书中

CA 对数字证书进行一个签名，确保该证书是可信的。（证书信任链问题）

本质：客户端信任服务端的问题

HTTPS 建立连接

SSL/TLS 协议基本流程：

客户端向服务器索要并验证服务器的公钥。

双方协商生产「会话秘钥」。

双方采用「会话秘钥」进行加密通信。

前两步就是 SSL/TLS 的建立过程，也就是 TLS 握手阶段，涉及四次通信（SSL/TLS 1.2）。

使用不同的密钥交换算法，TLS 握手流程也不一样，现在常用的密钥交换算法有两种：RSA 算法 和 ECDHE 算法。

ClientHello，由客户端向服务器发起加密通信请求

客户端随机数（Client Random） ...

SeverHello，服务器收到客户端请求后，向客户端发出响应

服务器端随机数（Server Random） + 服务器的数字证书 ...

客户端回应

公钥加密随机数 pre-master key + 客户端握手结束通知 ...

服务器的最后回应

服务器握手结束通知 + 握手摘要

至此，整个 TLS 的握手阶段结束，客户端与服务器进入加密通信，就完全是使用普通的 HTTP 协议，只不过用「会话秘钥」加密内容。

HTTPS 保证数据完整性

TLS 在实现上分为握手协议和记录协议两层：

TLS 握手协议即 TLS 四次握手的过程，负责协商加密算法和生成对称密钥；

TLS 记录协议负责保护应用程序数据并验证其完整性和来源，使用记录协议对 HTTP 数据加密；

TLS 记录协议主要负责消息（HTTP 数据）的压缩，加密及数据的认证：

将消息分割为多个较短的片段，然后分别对这些片段进行压缩

为经过压缩的片段加上消息认证码（MAC，通过哈希算法得到），这是为了保证数据完整性并进行数据的认证。

使用对称密钥对 压缩后的消息片顿 + 消息认证码 进行加密

加密后的数据再加上数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据。

记录协议完成后，最终的报文数据将传递到传输控制协议 (TCP) 层进行传输。

HTTP 的演变

HTTP/1.1 Vs. HTTP/1.0

长连接

支持管道（pipeline）网络传输，不必等响应就可发出接下来的请求

HTTP/2.0 Vs. HTTP/1.1

HTTP/2.0 基于 HTTPS，安全性高

头部压缩，HPACK 算法

二进制格式

并发传输，Stream，多个请求复用一个 TCP 连接

服务器推送

HTTP/2.0 依然存在队头阻塞问题，发生在 TCP 层，只有 TCP 数据是连续的，应用层才能从内核中读取到数据，一旦发生丢包，就会阻塞住所有的 HTTP 请求

HTTP/3

HTTP/3 下层使用 UDP 协议以解决队头阻塞问题。

基于 UDP 的 QUIC 协议可以实现类似 TCP 的可靠性传输，QUIC 协议有以下特点：

无队头阻塞：当某个流发生丢包时，只会阻塞这个流，不会影响其他流，多个 Stream 之间没有依赖，相互独立。

更快的连接建立：QUIC 内部包含了 TLS，仅需 1 个 RTT 就可以「同时」完成建立连接与密钥协商。

连接迁移：QUIC 协议没有用四元组的方式来 “绑定” 连接，而是通过连接 ID 来标记通信的两个端点。

安全性：在 HTTP/2.0 中，TLS 用于加密和认证整个 HTTP 会话，包括所有的 HTTP 头部和数据负载。TLS 的工作是在 TCP 层之上，它加密的是在 TCP 连接中传输的应用层的数据，并不会对 TCP 头部以及 TLS 记录层头部进行加密，所以在传输的过程中 TCP 头部可能会被攻击者篡改来干扰通信。而 HTTP/3.0 的 QUIC 对整个数据包（包括报文头和报文体）进行了加密与认证处理，保障安全性。

所以，QUIC 是一个在 UDP 之上的伪 TCP + TLS + HTTP/2 的多路复用的协议。

TCP_Interview

TCP 头格式

TCP 头部在不使用选项的话占用 20 个字节：

源端口号 (16 位) + 目标端口号 (16 位)

序列号 (32 位)：解决乱序问题

确认应答号 (32 位)：解决丢包问题

首部长度 (4 位) + 保留 (6 位) + 控制位 (6 位) + 窗口大小 (16 位)

校验和 (16 位) + 紧急指针 (16 位)

TCP 的存在意义

网络层的 IP 协议不保证可靠交付，如果需要保障网络数据包的可靠性，必须交由上层 (传输层) 的 TCP 协议来负责。

因为 TCP 协议是一个工作在传输层的可靠数据传输的服务，能确保收到的网络数据包是无损坏的、无间隔的、无冗余的、按序的。

什么是 TCP

TCP 是一个面向连接的、可靠的、基于字节流的传输层通信协议。

什么是 TCP 连接

连接：用于保证可靠性和流量控制维护的某些状态信息的组合，包括 socket、序列号、窗口大小。

建立 TCP 连接需要客户端与服务端达成以下信息的共识：

socket：TCP 四元组

序列号：用于解决乱序问题

窗口大小：用于流量控制

TCP 与 UDP 的区别

UDP 头部，固定为 8 个字节：

源端口号 (16 位) + 目的端口号 (16 位)

包长度 (16 位) + 校验和 (16 位)

UDP 只使用 IP 提供的面向无连接的通信服务。

TCP 与 UDP 的区别在于以下几点 (把握逻辑来记忆)：

连接：TCP 是面向连接的，UDP 是面向无连接的

服务对象：TCP 是端到端的两点服务，UDP 可以一对多

可靠性：TCP 是可靠交付数据的，UDP 是尽最大努力交付，不保证可靠交付

TCP 提供拥塞控制和流量控制机制，保证数据传输的安全性，UDP 没有

首部开销：TCP 不使用选项的情况首部为 20 个字节，UDP 首部固定为 8 个字节

传输方式：TCP 是基于字节流的流式传输，UDP 是以包为单位发送的，有边界

分片：TCP 数据大小如果大于 MSS 会在传输层进行分片，UDP 则只使用网络层 IP 协议的分片 (大于 MTU)

TCP 的应用场景：

FTP 文件传输

HTTP/HTTPS

UDP 的应用场景：

多媒体通信

广播通信

包总量较小的通信：如 DNS、SNMP 等

TCP 连接建立

TCP 建立连接是通过三次握手进行的。

为什么是三次握手，而不是两次、四次？

阻止重复历史连接的初始化

「旧 SYN 报文」称为历史连接，TCP 使用三次握手建立连接的最主要原因就是防止「历史连接」初始化了连接。

同步双方的初始序列号

客户端发送携带「初始序列号」的 SYN 报文的时候，需要服务端回一个 ACK 应答报文，表示客户端的 SYN 报文已被服务端成功接收，那当服务端发送「初始序列号」给客户端的时候，依然也要得到客户端的应答回应，这样一来一回，才能确保双方的初始序列号能被可靠的同步。

避免资源浪费

如果只有「两次握手」, 客户端发送的 SYN 报文在网络中阻塞了，重复发送多次 SYN 报文，那么服务端在收到请求后就会建立多个冗余的无效连接，造成不必要的资源浪费。

为什么建立 TCP 连接时要求初始化的序列号不一样？

防止历史报文被相同四元组的连接错误地接收 (主要方面)

防止黑客伪造相同序列号的 TCP 报文

初始化序列号 ISN 随机生成算法：ISN = M + F (localhost, localport, remotehost, remoteport)。

M 是一个计时器，这个计时器每隔 4 微秒加 1。

F 是一个 Hash 算法，根据源 IP、目的 IP、源端口、目的端口生成一个随机数值。要保证 Hash 算法不能被外部轻易推算得出，用 MD5 算法是一个比较好的选择。

随机数是会基于时钟计时器递增的，基本不可能会随机成一样的初始化序列号。

关于 SYN 攻击

假设攻击者短时间伪造不同 IP 地址的 SYN 报文，服务端每接收到一个 SYN 报文，就进入SYN_RCVD 状态，但服务端发送出去的 ACK + SYN 报文，无法得到未知 IP 主机的 ACK 应答，久而久之就会占满服务端的半连接队列，使得服务端不能为正常用户服务。

SYN 攻击方式最直接的表现就会把 TCP 半连接队列打满，这样当 TCP 半连接队列满了，后续再在收到 SYN 报文就会丢弃，导致客户端无法和服务端建立连接。

避免 SYN 攻击方式，可以有以下四种方法：

调大 netdev_max_backlog；

增大 TCP 半连接队列；

开启 tcp_syncookies；

减少 SYN+ACK 重传次数

TCP 连接断开

TCP 断开连接是通过四次挥手进行的，每个方向都需要一个 FIN 和一个 ACK。

关于 TIME_WAIT 状态

需要 TIME-WAIT 状态，主要是两个原因：

防止历史连接中的数据，被后面相同四元组的连接错误的接收；

TIME_WAIT 状态，状态会持续 2MSL 时长，这个时间足以让两个方向上的数据包都被丢弃，使得原来连接的数据包在网络中都自然消失，再出现的数据包一定都是新建立连接所产生的。(MSL 是 Maximum Segment Lifetime，报文最大生存时间。)

保证「被动关闭连接」的一方，能被正确的关闭；

TIME-WAIT 作用是等待足够的时间以确保最后的 ACK 能让被动关闭方接收，从而帮助其正常关闭。

假设客户端没有 TIME_WAIT 状态，而是在发完最后一次回 ACK 报文就直接进入 CLOSE 状态，如果该 ACK 报文丢失了，服务端则重传的 FIN 报文，而这时客户端已经进入到关闭状态了，在收到服务端重传的 FIN 报文后，就会回 RST 报文。

为了防止这种情况出现，客户端必须等待足够长的时间，确保服务端能够收到 ACK，如果服务端没有收到 ACK，那么就会触发 TCP 重传机制，服务端会重新发送一个 FIN，这样一去一来刚好两个 MSL 的时间。

客户端在收到服务端重传的 FIN 报文时，TIME_WAIT 状态的等待时间，会重置回 2MSL。

过多的 TIME-WAIT 状态主要的危害有两种：

第一是占用系统资源，比如文件描述符、内存资源、CPU 资源、线程资源等；

第二是占用端口资源，端口资源也是有限的，一般可以开启的端口为 32768～61000，也可以通过 net.ipv4.ip_local_port_range参数指定范围。

TIME_WAIT 是我们的朋友，它是有助于我们的，不要试图避免这个状态，而是应该弄清楚它。

如果服务端要避免过多的 TIME_WAIT 状态的连接，就永远不要主动断开连接，让客户端去断开，由分布在各处的客户端去承受 TIME_WAIT。

如果服务器出现大量的 TIME_WAIT 状态的 TCP 连接，就是说明服务器主动断开了很多 TCP 连接，有以下几种场景：

第一个场景：HTTP 没有使用长连接 (Keep-Alive)

第二个场景：HTTP 长连接超时

第三个场景：HTTP 长连接的请求数量达到上限

TCP 的保活机制

定义一个时间段，在这个时间段内，如果没有任何连接相关的活动，TCP 保活机制会开始作用，每隔一个时间间隔，发送一个探测报文，该探测报文包含的数据非常少，如果连续几个探测报文都没有得到响应，则认为当前的 TCP 连接已经死亡，系统内核将错误信息通知给上层应用程序。

TCP 保活的这个机制检测的时间是有点长，我们可以自己在应用层实现一个心跳机制。

Socket 编程

针对 TCP 进行 Socket 编程：

服务端和客户端初始化 socket，得到文件描述符；

服务端调用 bind，将 socket 绑定在指定的 IP 地址和端口；

服务端调用 listen，进行监听；

服务端调用 accept，等待客户端连接；

客户端调用 connect，向服务端的地址和端口发起连接请求；

服务端 accept 返回用于传输的 socket 的文件描述符；

客户端调用 write 写入数据；服务端调用 read 读取数据；

客户端断开连接时，会调用 close，那么服务端 read 读取数据的时候，就会读取到了 EOF，待处理完数据后，服务端调用 close，表示连接关闭。

服务端调用 accept 时，连接成功了会返回一个已完成连接的 socket，后续用来传输数据。监听的 socket 和真正用来传送数据的 socket，是「两个」socket，一个叫作监听 socket，一个叫作已完成连接 socket。

成功连接建立之后，双方开始通过 read 和 write 函数来读写数据，就像往一个文件流里面写东西一样。

IP_Base

IP 负责在「没有直连」的两个网络之间进行通信传输;

MAC 的作用是实现「直连」的两个设备之间通信;

IP 地址分类

分类地址： A 类、B 类、C 类、D 类、E 类。

无分类地址 CIDR：32 比特的 IP 地址被划分为两部分，前面是网络号，后面是主机号。

无类别域间路由（英语：Classless Inter-Domain Routing，简称CIDR）

子网掩码，掩码的意思就是掩盖掉主机号，剩余的就是网络号。将子网掩码和 IP 地址按位计算 AND，就可得到网络号。

可以通过子网掩码划分出网络号和主机号，那实际上子网掩码还有一个作用，那就是划分子网。

子网划分实际上是将主机地址分为两个部分：子网网络地址和子网主机地址。

IP 地址与路由控制

IP 地址的网络地址这一部分是用于进行路由控制。

路由控制表中记录着网络地址与下一步应该发送至路由器的地址。在主机和路由器上都会有各自的路由器控制表。

在发送 IP 包时，首先要确定 IP 包首部中的目标地址，再从路由控制表中找到与该地址具有相同网络地址的记录，根据该记录将 IP 包转发给相应的下一个路由器。如果路由控制表中存在多条相同网络地址的记录，就选择相同位数最多的网络地址，也就是最长匹配。

环回地址是在同一台计算机上的程序之间进行网络通信时所使用的一个默认地址。

计算机使用一个特殊的 IP 地址 127.0.0.1 作为环回地址。与该地址具有相同意义的是一个叫做 localhost 的主机名。使用这个 IP 或主机名时，数据包不会流向网络。

IP 分片与重组

每种数据链路的最大传输单元 MTU 都是不相同的，如 FDDI 数据链路 MTU 4352、以太网的 MTU 是 1500 字节等。

每种数据链路的 MTU 之所以不同，是因为每个不同类型的数据链路的使用目的不同。使用目的不同，可承载的 MTU 也就不同。

当 IP 数据包大小大于 MTU 时，IP 数据包就会被分片。

经过分片之后的 IP 数据报在被重组的时候，只能由目标主机进行，路由器是不会进行重组的。

在分片传输中，一旦某个分片丢失，则会造成整个 IP 数据报作废，所以 TCP 引入了 MSS 也就是在 TCP 层进行分片不由 IP 层分片，那么对于 UDP 我们尽量不要发送一个大于 MTU 的数据报文。

IPv6 基本认识

IPv4 地址长度共 32 位 (4 个字节)，是以每 8 位作为一组，并用点分十进制的表示方式。

IPv6 地址长度是 128 位 (16 个字节)，是以每 16 位作为一组，每组用冒号「:」隔开。

如果出现连续的 0 时还可以将这些 0 省略，并用两个冒号「::」隔开。但是，一个 IP 地址中只允许出现一次两个连续的冒号。

IPv6 不仅仅只是可分配的地址变多了，它还有非常多的亮点。

IPv6 可自动配置，即使没有 DHCP 服务器也可以实现自动分配 IP 地址，便捷到即插即用。

IPv6 包头包首部长度采用固定的值 40 字节，去掉了包头校验和，简化了首部结构，减轻了路由器负荷，大大提高了传输的性能。

IPv6 有应对伪造 IP 地址的网络安全功能以及防止线路窃听的功能，大大提升了安全性。

...

IPv6 相比 IPv4 的首部改进：

取消了首部校验和字段。 因为在数据链路层和传输层都会校验，因此 IPv6 直接取消了 IP 的校验。

取消了分片 / 重新组装相关字段。 分片与重组是耗时的过程，IPv6 不允许在中间路由器进行分片与重组，这种操作只能在源与目标主机，这将大大提高了路由器转发的速度。

取消选项字段。 选项字段不再是标准 IP 首部的一部分了，但它并没有消失，而是可能出现在 IPv6 首部中的「下一个首部」指出的位置上。删除该选项字段使的 IPv6 的首部成为固定长度的 40 字节。

IP 协议相关技术

DNS 域名解析

DNS 可以将域名网址自动转换为具体的 IP 地址

域名的层级关系类似一个树状结构：

根 DNS 服务器

顶级域 DNS 服务器（com）

权威 DNS 服务器（server.com）

浏览器首先看一下自己的缓存里有没有，如果没有就向操作系统的缓存要，还没有就检查本机域名解析文件 hosts，如果还是没有，就会 DNS 服务器进行查询，查询的过程如下：

客户端首先会发出一个 DNS 请求，问 www.server.com 的 IP 是啥，并发给本地 DNS 服务器（也就是客户端的 TCP/IP 设置中填写的 DNS 服务器地址）。

本地域名服务器收到客户端的请求后，如果缓存里的表格能找到 www.server.com，则它直接返回 IP 地址。如果没有，本地 DNS 会去问它的根域名服务器：“老大，能告诉我 www.server.com 的 IP 地址吗？” 根域名服务器是最高层次的，它不直接用于域名解析，但能指明一条道路。

根 DNS 收到来自本地 DNS 的请求后，发现后置是 .com，说：“www.server.com 这个域名归 .com 区域管理”，我给你 .com 顶级域名服务器地址给你，你去问问它吧。”

本地 DNS 收到顶级域名服务器的地址后，发起请求问 “老二，你能告诉我 www.server.com 的 IP 地址吗？”

顶级域名服务器说：“我给你负责 www.server.com 区域的权威 DNS 服务器的地址，你去问它应该能问到”。

本地 DNS 于是转向问权威 DNS 服务器：“老三，www.server.com 对应的 IP 是啥呀？”server.com 的权威 DNS 服务器，它是域名解析结果的原出处。为啥叫权威呢？就是我的域名我做主。

权威 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS。

本地 DNS 再将 IP 地址返回客户端，客户端和目标建立连接。

DNS 域名解析的过程就和我们日常生活中找人问路的过程类似，只指路不带路。

ARP 地址解析协议

ARP 是一个通过解析网络层地址来找寻数据链路层地址的网络传输协议。

ARP 是借助 ARP 请求与 ARP 响应两种类型的包确定 MAC 地址的。

主机会通过广播发送 ARP 请求，这个包中包含了想要知道的 MAC 地址的主机 IP 地址。

当同个链路中的所有设备收到 ARP 请求时，会去拆开 ARP 请求包里的内容，如果 ARP 请求包中的目标 IP 地址与自己的 IP 地址一致，那么这个设备就将自己的 MAC 地址塞入 ARP 响应包返回给主机。

操作系统通常会把第一次通过 ARP 获取的 MAC 地址缓存起来，以便下次直接从缓存中找到对应 IP 地址的 MAC 地址。

ARP 协议是已知 IP 地址求 MAC 地址，那 RARP 协议正好相反，它是已知 MAC 地址求 IP 地址。

另外，当发送主机和目的主机不在同一个局域网中时，即便知道对方的 MAC 地址，两者也不能直接通信，必须经过路由器进行 IP 层的转发才可以，因为路由器把这个局域网进行了链路层上的隔离 (除非进行网络层次的显示转发，否则路由器不会把一个局域网中的以太网帧自动的转发到另一个局域网或者外网中去，如果可以自动转发，可以想象有多可怕，无效的广播帧可能像洪水一样淹没整个网络，使得网络瘫痪，这也就是路由器的基本功能之一，隔离网络)，所以此时，发送主机会把一个网关 IP 地址作为目的 IP 地址 (这个是 IP 层决定的)，那么通过 ARP 协议获得的将不是目的主机的真实 MAC 地址，而是一台可以通往局域网外的路由器的 MAC 地址。于是此后发送主机发往目的主机的所有帧，都将发往该路由器，通过它向外发送。这种情况称为委托 ARP 或ARP 代理（ARP Proxy）。

DHCP 动态主机设置协议

DHCP 是一种使网络管理员能够集中管理和自动分配 IP 网络地址的通信协议。

DHCP 客户端进程监听的是 68 端口号，DHCP 服务端进程监听的是 67 端口号。

客户端首先发起 DHCP 发现报文（DHCP DISCOVER） 的 IP 数据报，由于客户端没有 IP 地址，也不知道 DHCP 服务器的地址，所以使用的是 UDP 广播通信，其使用的广播目的地址是 255.255.255.255（端口 67）并且使用 0.0.0.0（端口 68）作为源 IP 地址。DHCP 客户端将该 IP 数据报传递给链路层，链路层然后将帧广播到所有的网络中设备。

DHCP 服务器收到 DHCP 发现报文时，用 DHCP 提供报文（DHCP OFFER） 向客户端做出响应。该报文仍然使用 IP 广播地址 255.255.255.255，该报文信息携带服务器提供可租约的 IP 地址、子网掩码、默认网关、DNS 服务器以及 IP 地址租用期。

客户端收到一个或多个服务器的 DHCP 提供报文后，从中选择一个服务器，并向选中的服务器发送 DHCP 请求报文（DHCP REQUEST进行响应，回显配置的参数。

最后，服务端用 DHCP ACK 报文对 DHCP 请求报文进行响应，应答所要求的参数。

一旦客户端收到 DHCP ACK 后，交互便完成了，并且客户端能够在租用期内使用 DHCP 服务器分配的 IP 地址。

如果租约的 DHCP IP 地址快过期了，客户端会向服务器发送 DHCP 请求报文：

服务器如果同意继续租用，则用 DHCP ACK 报文进行应答，客户端就会延长租期。

服务器如果不同意继续租用，则用 DHCP NACK 报文，客户端就要停止使用租约的 IP 地址。

可以发现，DHCP 交互中，全程都是使用 UDP 广播通信。

有了 DHCP 中继代理以后，对不同网段的 IP 地址分配也可以由一个 DHCP 服务器统一进行管理。

DHCP 客户端会向 DHCP 中继代理发送 DHCP 请求包，而 DHCP 中继代理在收到这个广播包以后，再以单播的形式发给 DHCP 服务器。

服务器端收到该包以后再向 DHCP 中继代理返回应答，并由 DHCP 中继代理将此包广播给 DHCP 客户端。

因此，DHCP 服务器即使不在同一个链路上也可以实现统一分配和管理 IP 地址。

NAT 网络地址转换

网络地址转换（英语：Network Address Translation，缩写：NAT），又称 IP 动态伪装（英语：IP Masquerade），是一种在 IP 数据包通过路由器或防火墙时重写来源或目的 IP 地址或端口的技术。 这种技术普遍应用于有多台主机，但只通过一个公有 IP 地址访问互联网的私有网络中。

简单的来说 NAT 就是同个公司、家庭、教室内的主机对外部通信时，把私有 IP 地址转换成公有 IP 地址。

可以把 IP 地址 + 端口号一起进行转换。这样，就用一个全球 IP 地址就可以了，这种转换技术就叫网络地址与端口转换 NAPT。

NAPT 路由器的转换表，可以正确地转换地址跟端口的组合。

由于 NAT/NAPT 都依赖于自己的转换表，因此会有以下的问题：

外部无法主动与 NAT 内部服务器建立连接，因为 NAPT 转换表没有转换记录。

转换表的生成与转换操作都会产生性能开销。

通信过程中，如果 NAT 路由器重启了，所有的 TCP 连接都将被重置。

解决的方法主要有两种方法。

第一种就是改用 IPv6

NAT 穿透技术

在 NAT 穿透技术中，NAT 设备后的应用程序处于主动地位，它已经明确地知道 NAT 设备要修改它外发的数据包，于是它主动配合 NAT 设备的操作，主动地建立好映射，这样就不像以前由 NAT 设备来建立映射了。

客户端主动从 NAT 设备获取公有 IP 地址，然后自己建立端口映射条目，然后用这个条目对外通信，就不需要 NAT 设备来进行转换了。

ICMP

ICMP 全称是 Internet Control Message Protocol，也就是互联网控制报文协议。

ICMP 主要的功能包括：确认 IP 包是否成功送达目标地址、报告发送过程中 IP 包被废弃的原因和改善网络设置等。

ICMP 大致可以分为两大类：

一类是用于诊断的查询消息，也就是「查询报文类型」

另一类是通知出错原因的错误消息，也就是「差错报文类型」

IGMP

IGMP 是因特网组管理协议，工作在主机（组播成员）和最后一跳路由之间。

IGMP 报文向路由器申请加入和退出组播组，默认情况下路由器是不会转发组播包到连接中的主机，除非主机通过 IGMP 加入到组播组，主机申请加入到组播组时，路由器就会记录 IGMP 路由器表，路由器后续就会转发组播包到对应的主机了。

IGMP 报文采用 IP 封装，IP 头部的协议号为 2，而且 TTL 字段值通常为 1，因为 IGMP 是工作在主机与连接的路由器之间。

组播地址不是用于机器 ip 地址的，因为组播地址没有网络号和主机号，所以跟 dhcp 没关系。组播地址一般是用于 udp 协议，机器发送 UDP 组播数据时，目标地址填的是组播地址，那么在组播组内的机器都能收到数据包。

是否加入组播组和离开组播组，是由 socket 一个接口实现的，主机 ip 是不用改变的。

Others

OSPF（Open Shortest Path First，开放式最短路径优先）：一种内部网关协议（Interior Gateway Protocol，IGP），也是广泛使用的一种动态路由协议，基于链路状态算法，考虑了链路的带宽、延迟等因素来选择最佳路径。

RIP (Routing Information Protocol，路由信息协议）：一种内部网关协议（Interior Gateway Protocol，IGP），也是一种动态路由协议，基于距离向量算法，使用固定的跳数作为度量标准，选择跳数最少的路径作为最佳路径。

BGP（Border Gateway Protocol，边界网关协议）：一种用来在路由选择域之间交换网络层可达性信息（Network Layer Reachability Information，NLRI）的路由选择协议，具有高度的灵活性和可扩展性。