【网络】传输层协议UDP/TCP&&网络层IP&&数据链路层MAC&&NAT详解
【网络】传输层协议UDP/TCP&&网络层IP&&数据链路层MAC&&NAT详解
主页:醋溜马桶圈-CSDN博客
目录
2.5.3 解决 TIME_WAIT 状态引起的 bind 失败的方法
1.传输层协议 UDP
1.1 传输层
负责数据能够从发送端传输接收端
1.2 端口号
端口号(Port)标识了一个主机上进行通信的不同的应用程序
在 TCP/IP 协议中,用 "源 IP","源端口号","目的 IP","目的端口号","协议号" 这样一个五元组来标识一个通信(可以通过 netstat -n 查看)
端口号范围划分
- 0 - 1023:知名端口号,HTTP,FTP,SSH 等这些广为使用的应用层协议,他们的端口号都是固定的
- 1024 - 65535:操作系统动态分配的端口号,客户端程序的端口号,就是由操作系统从这个范围分配的
认识知名端口号(Well-Know Port Number)
有些服务器是非常常用的,为了使用方便,人们约定一些常用的服务器,都是用以下这些
固定的端口号:
- ssh 服务器,使用 22 端口
- ftp 服务器,使用 21 端口
- telnet 服务器,使用 23 端口
- http 服务器, 使用 80 端口
- https 服务器,使用 443
执行下面的命令,可以看到知名端口号
cat /etc/services
我们自己写一个程序使用端口号时,要避开这些知名端口号
- 一个进程是否可以 bind 多个端口号? 可以
- 一个端口号是否可以被多个进程 bind? 不可以
1.3 UDP 协议
1.3.1 UDP 协议端格式
- 16 位 UDP 长度,表示整个数据报(UDP 首部+UDP 数据)的最大长度
- 如果校验和出错,就会直接丢弃
1.3.2 UDP 的特点
UDP 传输的过程类似于寄信
- 无连接:知道对端的 IP 和端口号就直接进行传输,不需要建立连接
- 不可靠:没有确认机制,没有重传机制,如果因为网络故障该段无法发到对方,UDP 协议层也不会给应用层返回任何错误信息
- 面向数据报:不能够灵活的控制读写数据的次数和数量
1.3.3 面向数据报
应用层交给 UDP 多长的报文,UDP 原样发送,既不会拆分,也不会合并
用 UDP 传输 100 个字节的数据:
- 如果发送端调用一次 sendto,发送 100 个字节,那么接收端也必须调用对应的一次 recvfrom,接收 100 个字节,而不能循环调用 10 次 recvfrom,每次接收 10 个字节
1.3.4 UDP 的缓冲区
- UDP 没有真正意义上的 发送缓冲区,调用 sendto 会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作
- UDP 具有接收缓冲区,但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致,如果缓冲区满了,再到达的 UDP 数据就会被丢弃
UDP 的 socket 既能读,也能写,这个概念叫做 全双工
1.3.5 UDP 使用注意事项
我们注意到,UDP 协议首部中有一个 16 位的最大长度,也就是说一个 UDP 能传输的数据最大长度是 64K(包含 UDP 首部)
然而 64K 在当今的互联网环境下,是一个非常小的数字
如果我们需要传输的数据超过 64K,就需要在应用层手动的分包,多次发送,并在接收端手动拼装
1.3.6 基于 UDP 的应用层协议
- NFS:网络文件系统
- TFTP:简单文件传输协议
- DHCP:动态主机配置协议
- BOOTP:启动协议(用于无盘设备启动)
- DNS:域名解析协议
当然,:也包括自己写 UDP 程序时自定义的应用层协议
2.传输层协议 TCP
2.1 TCP 协议
TCP 全称为 "传输控制协议(Transmission Control Protocol")
人如其名,要对数据的传输进行一个详细的控制
2.2 TCP 协议段格式
- 源/目的端口号:表示数据是从哪个进程来,,到哪个进程去;
- 32 位序号/32 位确认号
- 4 位 TCP 报头长度: 表示该 TCP 头部有多少个 32 位 bit(有多少个 4 字节),所以TCP 头部最大长度是 15 * 4 = 60
- 6 位标志位:
○ URG:紧急指针是否有效
○ ACK:确认号是否有效
○ PSH:提示接收端应用程序立刻从 TCP 缓冲区把数据读走
○ RST:对方要求重新建立连接,我们把携带 RST 标识的称为复位报文段
○ SYN:请求建立连接,我们把携带 SYN 标识的称为同步报文段
○ FIN:通知对方,本端要关闭了,我们称携带 FIN 标识的为结束报文段
- 16 位窗口大小
- 16 位校验和:发送端填充,CRC 校验,接收端校验不通过,则认为数据有问题,此处的检验和不光包含 TCP 首部,也包含 TCP 数据部分
- 16 位紧急指针:标识哪部分数据是紧急数据
- 40 字节头部选项
2.3 确认应答(ACK)机制
TCP 将每个字节的数据都进行了编号,即为序列号
每一个 ACK 都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据,下一次你从哪里开始发
2.4 超时重传机制
- 主机 A 发送数据给 B 之后,可能因为网络拥堵等原因,数据无法到达主机 B
- 如果主机 A 在一个特定时间间隔内没有收到 B 发来的确认应答,就会进行重发
但是,主机 A 未收到 B 发来的确认应答,也可能是因为 ACK 丢失了
因此主机 B 会收到很多重复数据,那么 TCP 协议需要能够识别出那些包是重复的包,并且把重复的丢弃掉
这时候我们可以利用前面提到的序列号,就可以很容易做到去重的效果
那么,如果超时的时间如何确定?
- 最理想的情况下,找到一个最小的时间,保证 "确认应答一定能在这个时间内返回"
- 但是这个时间的长短,随着网络环境的不同,是有差异的
- 如果超时时间设的太长,会影响整体的重传效率
- 如果超时时间设的太短,有可能会频繁发送重复的包
TCP 为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间
- Linux 中(BSD Unix 和 Windows 也是如此),超时以 500ms 为一个单位进行控制,每次判定超时重发的超时时间都是 500ms 的整数倍
- 如果重发一次之后,仍然得不到应答,等待 2*500ms 后再进行重传
- 如果仍然得不到应答,等待 4*500ms 进行重传,依次类推,以指数形式递增
- 累计到一定的重传次数,TCP 认为网络或者对端主机出现异常,强制关闭连接
2.5 连接管理机制
在正常情况下,TCP 要经过三次握手建立连接,四次挥手断开连接
2.5.1 服务端状态转化
- [CLOSED -> LISTEN]
服务器端调用 listen 后进入 LISTEN 状态, 等待客户端连接; - [LISTEN -> SYN_RCVD]
一旦监听到连接请求(同步报文段),就将该连接放入内核等待队列中,并向客户端发送 SYN 确认报文 - [SYN_RCVD -> ESTABLISHED]
服务端一旦收到客户端的确认报文,就进入ESTABLISHED 状态,可以进行读写数据了. - [ESTABLISHED -> CLOSE_WAIT]
当客户端主动关闭连接(调用 close),服务器会收到结束报文段,服务器返回确认报文段并进入 CLOSE_WAIT - [CLOSE_WAIT -> LAST_ACK]
进入 CLOSE_WAIT 后说明服务器准备关闭连接(需要处理完之前的数据),当服务器真正调用 close 关闭连接时,会向客户端发送FIN,此时服务器进入 LAST_ACK 状态,等待最后一个 ACK 到来(这个 ACK 是客户端确认收到了 FIN) - [LAST_ACK -> CLOSED]
服务器收到了对 FIN 的 ACK,彻底关闭连接,客户端状态转化 - [CLOSED -> SYN_SENT]
客户端调用 connect,发送同步报文段 - [SYN_SENT -> ESTABLISHED]
connect 调用成功,则进入 ESTABLISHED 状态,开始读写数据 - [ESTABLISHED -> FIN_WAIT_1]
客户端主动调用 close 时,向服务器发送结束报文段,同时进入 FIN_WAIT_1 - [FIN_WAIT_1 -> FIN_WAIT_2]
客户端收到服务器对结束报文段的确认,则进入 FIN_WAIT_2,开始等待服务器的结束报文段 - [FIN_WAIT_2 -> TIME_WAIT]
客户端收到服务器发来的结束报文段,进入TIME_WAIT,并发出 LAST_ACK - [TIME_WAIT -> CLOSED]
客户端要等待一个 2MSL(Max Segment Life,报文最大生存时间)的时间,才会进入 CLOSED 状态
下图是 TCP 状态转换的一个汇总
- 较粗的虚线表示服务端的状态变化情况
- 较粗的实线表示客户端的状态变化情况
- CLOSED 是一个假想的起始点,不是真实状态
2.5.2 理解 TIME_WAIT 状态
现在做一个测试,首先启动 server,然后启动 client,然后用 Ctrl-C 使 server 终止,这时马上再运行 server,结果是
这是因为,虽然 server 的应用程序终止了,但 TCP 协议层的连接并没有完全断开,因此不能再次监听同样的 server 端口,我们用 netstat 命令查看一下
- TCP 协议规定,主动关闭连接的一方要处于 TIME_ WAIT 状态,等待两个MSL(maximum segment lifetime)的时间后才能回到 CLOSED 状态
- 我们使用 Ctrl-C 终止了 server,所以 server 是主动关闭连接的一方,在TIME_WAIT 期间仍然不能再次监听同样的 server 端口
- MSL 在 RFC1122 中规定为两分钟,但是各操作系统的实现不同, 在 Centos7 和 Ubuntu 上默认配置的值是 60s
- 可以通过 cat /proc/sys/net/ipv4/tcp_fin_timeout 查看 msl 的值
为什么是 TIME_WAIT 的时间是 2MSL?
- MSL 是 TCP 报文的最大生存时间,因此 TIME_WAIT 持续存在 2MSL 的话
- 就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启,可能会收到来自上一个进程的迟到的数据,但是这种数据很可能是错误的)
- 同时也是在理论上保证最后一个报文可靠到达(假设最后一个 ACK 丢失,那么服务器会再重发一个 FIN,这时虽然客户端的进程不在了,但是 TCP 连接还在,仍然可以重发 LAST_ACK)
2.5.3 解决 TIME_WAIT 状态引起的 bind 失败的方法
在 server 的 TCP 连接没有完全断开之前不允许重新监听,某些情况下可能是不合理的
- 服务器需要处理非常大量的客户端的连接(每个连接的生存时间可能很短,但是每秒都有很大数量的客户端来请求)
- 这个时候如果由服务器端主动关闭连接(比如某些客户端不活跃,就需要被服务器端主动清理掉)就会产生大量 TIME_WAIT 连接
- 由于我们的请求量很大,就可能导致 TIME_WAIT 的连接数很多,每个连接都会占用一个通信五元组(源 ip,源端口,目的 ip,目的端口,协议)其中服务器的 ip 和端口和协议是固定的, 如果新来的客户端连接的 ip 和端口号和 TIME_WAIT 占用的链接重复了,就会出现问题
使用 setsockopt()设置 socket 描述符的 选项 SO_REUSEADDR 为 1,表示允许创建端口号相同但 IP 地址不同的多个 socket 描述符
2.5.4 理解 CLOSE_WAIT 状态
编译运行没有close函数的服务器,启动客户端链接,查看 TCP 状态, 客户端服务器都为
ESTABLELISHED 状态, 没有问题
然后我们关闭客户端程序, 观察 TCP 状态
tcp 0 0 0.0.0.0:9090 0.0.0.0:* LISTEN 5038/./dict_server
tcp 0 0 127.0.0.1:49958 127.0.0.1:9090 FIN_WAIT2 -
tcp 0 0 127.0.0.1:9090 127.0.0.1:49958 CLOSE_WAIT 5038/./dict_server
此时服务器进入了 CLOSE_WAIT 状态,结合我们四次挥手的流程图,可以认为四次挥手没有正确完成
小结:对于服务器上出现大量的 CLOSE_WAIT 状态,原因就是服务器没有正确的关闭socket,导致四次挥手没有正确完成,这是一个 BUG,只需要加上对应的 close 即可解决问题
2.6 滑动窗口
确认应答策略,对每一个发送的数据段,都要给一个 ACK 确认应答,收到 ACK 后再发送下一个数据段
这样做有一个比较大的缺点,就是性能较差,尤其是数据往返的时间较长的时候
既然这样一发一收的方式性能较低,那么我们一次发送多条数据,就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了)
- 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值,上图的窗口大小就是 4000 个字节(四个段)
- 发送前四个段的时候,不需要等待任何 ACK,直接发送
- 收到第一个 ACK 后,滑动窗口向后移动,继续发送第五个段的数据,依次类推
- 操作系统内核为了维护这个滑动窗口,需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答,只有确认应答过的数据,才能从缓冲区删掉
- 窗口越大,则网络的吞吐率就越高
那么如果出现了丢包,如何进行重传? 这里分两种情况讨论
情况一:数据包已经抵达,ACK 被丢了
这种情况下,部分 ACK 丢了并不要紧,因为可以通过后续的 ACK 进行确认
情况二:数据包就直接丢了
- 当某一段报文段丢失之后,发送端会一直收到 1001 这样的 ACK,就像是在提醒发送端 "我想要的是 1001" 一样
- 如果发送端主机连续三次收到了同样一个 "1001" 这样的应答,就会将对应的数据 1001 - 2000 重新发送
- 这个时候接收端收到了 1001 之后,再次返回的 ACK 就是 7001 了(因为 2001 - 7000)接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中
这种机制被称为 "高速重发控制"(也叫 "快重传")
2.7 流量控制
接收端处理数据的速度是有限的,如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应
因此 TCP 支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制(Flow Control)
- 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 "窗口大小" 字段,通过 ACK 端通知发送端
- 窗口大小字段越大,说明网络的吞吐量越高
- 接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端
- 发送端接受到这个窗口之后,就会减慢自己的发送速度
- 如果接收端缓冲区满了,就会将窗口置为 0,这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端
接收端如何把窗口大小告诉发送端呢?
TCP 首部中有一个 16 位窗口字段,就是存放了窗口大小信息
那么问题来了,16 位数字最大表示 65535,那么 TCP 窗口最大就是 65535 字节么?
实际上,TCP 首部 40 字节选项中还包含了一个窗口扩大因子 M,实际窗口大小是 窗口字段的值左移 M 位
2.9 拥塞控制
虽然 TCP 有了滑动窗口这个大杀器,能够高效可靠的发送大量的数据,但是如果在刚开始阶段就发送大量的数据,仍然可能引发问题
因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵,在不清楚当前网络状态下,贸然发送大量的数据,是很有可能引起雪上加霜的
TCP 引入 慢启动 机制,先发少量的数据探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据
- 此处引入一个概念称为拥塞窗口
- 发送开始的时候, 定义拥塞窗口大小为 1
- 每次收到一个 ACK 应答, 拥塞窗口加 1
- 每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为实际发送的窗口
像上面这样的拥塞窗口增长速度,是指数级别的,"慢启动" 只是指初使时慢,但是增长速度非常快
- 为了不增长的那么快,因此不能使拥塞窗口单纯的加倍
- 此处引入一个叫做慢启动的阈值
- 当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长
- 当 TCP 开始启动的时候,启动阈值等于窗口最大值
- 在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回 1
- 少量的丢包,我们仅仅是触发超时重传,大量的丢包,我们就认为网络拥塞
- 当 TCP 通信开始后,网络吞吐量会逐渐上升,随着网络发生拥堵,吞吐量会立刻下降,
- 拥塞控制,归根结底是 TCP 协议想尽可能快的把数据传输给对方,但是又要避免给网络造成太大压力的折中方案
2.10 延迟应答
如果接收数据的主机立刻返回 ACK 应答,这时候返回的窗口可能比较小
- 假设接收端缓冲区为 1M,一次收到了 500K 的数据,如果立刻应答,返回的窗口就是 500K
- 但实际上可能处理端处理的速度很快,10ms 之内就把 500K 数据从缓冲区消费掉了
- 在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来
- 如果接收端稍微等一会再应答,比如等待 200ms 再应答,那么这个时候返回的窗口大小就是 1M
一定要记得,窗口越大,网络吞吐量就越大,传输效率就越高,我们的目标是在保证网络不拥塞的情况下尽量提高传输效率
那么所有的包都可以延迟应答么? 肯定也不是
- 数量限制:每隔 N 个包就应答一次
- 时间限制:超过最大延迟时间就应答一次
具体的数量和超时时间,依操作系统不同也有差异
一般 N 取 2,超时时间取 200ms
2.11 捎带应答
在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是 "一发一收" 的,意味着客户端给服务器说了 "How are you",服务器也会给客户端回一个 "Fine, thank you"
那么这个时候 ACK 就可以搭顺风车,和服务器回应的 "Fine, thank you" 一起回给客户端
2.12 面向字节流
创建一个 TCP 的 socket, 同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区;
- 调用 write 时,数据会先写入发送缓冲区中
- 如果发送的字节数太长,会被拆分成多个 TCP 的数据包发出
- 如果发送的字节数太短,就会先在缓冲区里等待,等到缓冲区长度差不多了,或者其他合适的时机发送出去
- 接收数据的时候,数据也是从网卡驱动程序到达内核的接收缓冲区
- 然后应用程序可以调用 read 从接收缓冲区拿数据
- 另一方面,TCP 的一个连接,既有发送缓冲区,也有接收缓冲区,那么对于这一个连接,既可以读数据,也可以写数据,这个概念叫做 全双工
由于缓冲区的存在,TCP 程序的读和写不需要一一匹配,例如:
- 写 100 个字节数据时,可以调用一次 write 写 100 个字节,也可以调用 100 次 write,每次写一个字节
- 读 100 个字节数据时,也完全不需要考虑写的时候是怎么写的,既可以一次 read 100 个字节,也可以一次 read 一个字节,重复 100 次
2.13 粘包问题
- 首先要明确, 粘包问题中的 "包",是指的应用层的数据包
- 在 TCP 的协议头中,没有如同 UDP 一样的 "报文长度" 这样的字段,但是有一个序号这样的字段
- 站在传输层的角度,TCP 是一个一个报文过来的,按照序号排好序放在缓冲区中
- 站在应用层的角度,看到的只是一串连续的字节数据
- 那么应用程序看到了这么一连串的字节数据,就不知道从哪个部分开始到哪个部分,是一个完整的应用层数据包
那么如何避免粘包问题呢? 归根结底就是一句话,明确两个包之间的边界
- 对于定长的包,保证每次都按固定大小读取即可,例如上面的 Request 结构,是固定大小的,那么就从缓冲区从头开始按 sizeof(Request)依次读取即可
- 对于变长的包,可以在包头的位置,约定一个包总长度的字段,从而就知道了包的结束位置
- 对于变长的包,还可以在包和包之间使用明确的分隔符(应用层协议,是程序猿自己来定的,只要保证分隔符不和正文冲突即可)
思考:对于 UDP 协议来说,是否也存在 "粘包问题" 呢?
- 对于 UDP,如果还没有上层交付数据,UDP 的报文长度仍然在,同时,UDP 是一个一个把数据交付给应用层,就有很明确的数据边界
- 站在应用层的站在应用层的角度,使用 UDP 的时候,要么收到完整的 UDP 报文,要么不收,不会出现"半个"的情况.
2.14 TCP 异常情况
- 进程终止:进程终止会释放文件描述符,仍然可以发送 FIN,和正常关闭没有什么区别
- 机器重启:和进程终止的情况相同
- 机器掉电/网线断开:接收端认为连接还在,一旦接收端有写入操作,接收端发现连接已经不在了,就会进行 reset,即使没有写入操作,TCP 自己也内置了一个保活定时器,会定期询问对方是否还在,如果对方不在,也会把连接释放
- 另外,应用层的某些协议,也有一些这样的检测机制,例如 HTTP 长连接中,也会定期检测对方的状态,例如 QQ,在 QQ 断线之后,也会定期尝试重新连接
2.15 TCP 小结
为什么 TCP 这么复杂? 因为要保证可靠性,同时又尽可能的提高性能
可靠性:
- 校验和
- 序列号(按序到达)
- 确认应答
- 超时重发
- 连接管理
- 流量控制
- 拥塞控制
提高性能:
- 滑动窗口
- 快速重传
- 延迟应答
- 捎带应答
其他:
- 定时器(超时重传定时器,保活定时器,TIME_WAIT 定时器等)
2.16 基于 TCP 应用层协议
- HTTP
- HTTPS
- SSH
- Telnet
- FTP
- SMTP
当然,也包括你自己写 TCP 程序时自定义的应用层协议
2.17 TCP/UDP 对比
我们说了 TCP 是可靠连接,那么是不是 TCP 一定就优于 UDP 呢? TCP 和 UDP 之间的优点和缺点,不能简单,绝对的进行比较
- TCP 用于可靠传输的情况,应用于文件传输,重要状态更新等场景
- UDP 用于对高速传输和实时性要求较高的通信领域,例如,早期的 QQ、视频传输等,另外 UDP 可以用于广播
归根结底,TCP 和 UDP 都是程序员的工具,什么时机用,具体怎么用,还是要根据具体的需求场景去判定
3.网络层
在复杂的网络环境中确定一个合适的路径
3.1 IP 协议
- 主机:配有 IP 地址,但是不进行路由控制的设备
- 路由器:即配有 IP 地址,又能进行路由控制
- 节点:主机和路由器的统称
3.2 协议头格式
- 4 位版本号(version)
指定 IP 协议的版本,对于 IPv4 来说,就是 4 - 4 位头部长度(header length)
IP 头部的长度是多少个 32bit,也就是 length 4 的字节数,4bit 表示最大的数字是 15,因此 IP 头部最大长度是 60 字节 - 8 位服务类型(Type Of Service)
3 位优先权字段(已经弃用),4 位 TOS 字段,和 1 位保留字段(必须置为 0),4 位 TOS 分别表示:最小延时,最大吞吐量,最高可靠性,最小成本;这四者相互冲突,只能选择一个,对于 ssh/telnet 这样的应用程序,最小延时比较重要;对于 ftp 这样的程序,最大吞吐量比较重要 - 16 位总长度(total length)
IP 数据报整体占多少个字节 - 16 位标识(id)
唯一的标识主机发送的报文,如果 IP 报文在数据链路层被分片了,那么每一个片里面的这个 id 都是相同的 - 3 位标志字段
第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到),第二位置为 1 表示禁止分片,这时候如果报文长度超过 MTU,IP 模块就会丢弃报文,第三位表示"更多分片",如果分片了的话,最后一个分片置为 0,其他是 1,类似于一个结束标记 - 13 位分片偏移(framegament offset)
是分片相对于原始 IP 报文开始处的偏移,其实就是在表示当前分片在原报文中处在哪个位置,实际偏移的字节数是这个值 8 得到的,因此,除了最后一个报文之外,其他报文的长度必须是 8 的整数倍(否则报文就不连续了) - 8 位生存时间(Time To Live, TTL)
数据报到达目的地的最大报文跳数,一般是64,每次经过一个路由,TTL -= 1,一直减到 0 还没到达,那么就丢弃了,这个字段主要是用来防止出现路由循环 - 8 位协议
表示上层协议的类型 - 16 位头部校验和
使用 CRC 进行校验,来鉴别头部是否损坏 - 32 位源地址和 32 位目标地址
表示发送端和接收端 - 选项字段(不定长,最多 40 字节)
3.3 网段划分
IP 地址分为两个部分,网络号和主机号
- 网络号:保证相互连接的两个网段具有不同的标识
- 主机号:同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号
- 不同的子网其实就是把网络号相同的主机放到一起
- 如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复
通过合理设置主机号和网络号,就可以保证在相互连接的网络中,每台主机的 IP 地址都不相同
那么问题来了,手动管理子网内的 IP,是一个相当麻烦的事情
- 有一种技术叫做 DHCP,能够自动的给子网内新增主机节点分配 IP 地址,避免了手动管理 IP 的不便
- 一般的路由器都带有 DHCP 功能,因此路由器也可以看做一个 DHCP 服务器
过去曾经提出一种划分网络号和主机号的方案,把所有 IP 地址分为五类,如下图所示
- A 类 0.0.0.0 到 127.255.255.255
- B 类 128.0.0.0 到 191.255.255.255
- C 类 192.0.0.0 到 223.255.255.255
- D 类 224.0.0.0 到 239.255.255.255
- E 类 240.0.0.0 到 247.255.255.255
随着 Internet 的飞速发展,这种划分方案的局限性很快显现出来,大多数组织都申请 B 类网络地址,导致 B 类地址很快就分配完了,而 A 类却浪费了大量地址
- 例如,申请了一个 B 类地址,理论上一个子网内能允许 6 万 5 千多个主机,A 类地址的子网内的主机数更多
- 实际网络架设中,不会存在一个子网内有这么多的情况,因此大量的 IP 地址都被浪费掉了
针对这种情况提出了新的划分方案,称为 CIDR(Classless Interdomain Routing)
- 引入一个额外的子网掩码(subnet mask)来区分网络号和主机号
- 子网掩码也是一个 32 位的正整数,通常用一串 "0" 来结尾
- 将 IP 地址和子网掩码进行 "按位与" 操作,得到的结果就是网络号
- 网络号和主机号的划分与这个 IP 地址是 A 类、B 类还是 C 类无关
可见,IP 地址与子网掩码做与运算可以得到网络号,主机号从全 0 到全 1 就是子网的地址范围
IP 地址和子网掩码还有一种更简洁的表示方法,例如 140.252.20.68/24,表示 IP 地址为 140.252.20.68,子网掩码的高 24 位是 1,也就是 255.255.255.0
3.3.1 特殊的 IP 地址
- 将 IP 地址中的主机地址全部设为 0,就成为了网络号,代表这个局域网
- 将 IP 地址中的主机地址全部设为 1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包
- 127.*的 IP 地址用于本机环回(loop back)测试,通常是 127.0.0.1
3.3.2 IP 地址的数量限制
我们知道,IP 地址(IPv4)是一个 4 字节 32 位的正整数,那么一共只有 2 的 32 次方 个 IP地址,大概是 43 亿左右,而 TCP/IP 协议规定,每个主机都需要有一个 IP 地址
这意味着,一共只有 43 亿台主机能接入网络么?
实际上,由于一些特殊的 IP 地址的存在,数量远不足 43 亿;另外 IP 地址并非是按照主机台数来配置的,而是每一个网卡都需要配置一个或多个 IP 地址
CIDR 在一定程度上缓解了 IP 地址不够用的问题(提高了利用率,减少了浪费,但是 IP 地址的绝对上限并没有增加),仍然不是很够用,这时候有三种方式来解决:
- 动态分配 IP 地址:只给接入网络的设备分配 IP 地址,因此同一个 MAC 地址的设备,每次接入互联网中,得到的 IP 地址不一定是相同的;
- NAT 技术
- IPv6:IPv6 并不是 IPv4 的简单升级版,这是互不相干的两个协议,彼此并不兼容;IPv6 用 16 字节 128 位来表示一个 IP 地址,但是目前 IPv6 还没有普及
3.3.3 私有 IP 地址和公网 IP 地址
如果一个组织内部组建局域网,IP 地址只用于局域网内的通信,而不直接连到 Internet 上,理论上使用任意的 IP 地址都可以,但是 RFC 1918 规定了用于组建局域网的私有 IP 地址
- 10.*:前 8 位是网络号,共 16,777,216 个地址
- 172.16.*到 172.31.*:前 12 位是网络号,共 1,048,576 个地址
- 192.168.*:前 16 位是网络号,共 65,536 个地址
包含在这个范围中的,都成为私有 IP,其余的则称为全局 IP(或公网 IP)
- 一个路由器可以配置两个 IP 地址,一个是 WAN 口 IP,一个是 LAN 口 IP(子网IP)
- 路由器 LAN 口连接的主机,都从属于当前这个路由器的子网中
- 不同的路由器,子网 IP 其实都是一样的(通常都是 192.168.1.1),子网内的主机IP 地址不能重复,但是子网之间的 IP 地址就可以重复了
- 每一个家用路由器,其实又作为运营商路由器的子网中的一个节点,这样的运营商路由器可能会有很多级,最外层的运营商路由器,WAN 口 IP 就是一个公网 IP 了
- 子网内的主机需要和外网进行通信时,路由器将 IP 首部中的 IP 地址进行替换(替换成 WAN 口 IP),这样逐级替换,最终数据包中的 IP 地址成为一个公网 IP,这种技术称为 NAT(Network Address Translation,网络地址转换)
- 如果希望我们自己实现的服务器程序,能够在公网上被访问到,就需要把程序部署在一台具有外网 IP 的服务器上,这样的服务器可以在阿里云/腾讯云上进行购买
3.4 路由
在复杂的网络结构中,找出一条通往终点的路线
路由的过程,就是这样一跳一跳(Hop by Hop) "问路" 的过程
所谓 "一跳" 就是数据链路层中的一个区间,具体在以太网中指从源 MAC 地址到目的 MAC 地址之间的帧传输区间
IP 数据包的传输过程和问路一样
- 当 IP 数据包,到达路由器时,路由器会先查看目的 IP
- 路由器决定这个数据包是能直接发送给目标主机,还是需要发送给下一个路由器
- 依次反复,一直到达目标 IP 地址
那么如何判定当前这个数据包该发送到哪里呢? 这个就依靠每个节点内部维护一个路由表
- 路由表可以使用 route 命令查看
- 如果目的 IP 命中了路由表,就直接转发即可
- 路由表中的最后一行,主要由下一跳地址和发送接口两部分组成,当目的地址与路由表中其它行都不匹配时,就按缺省路由条目规定的接口发送到下一跳地址
假设某主机上的网络接口配置和路由表如下
- 这台主机有两个网络接口,一个网络接口连到 192.168.10.0/24 网络,另一个网络接口连到 192.168.56.0/24 网络
- 路由表的 Destination 是目的网络地址,Genmask 是子网掩码,Gateway 是下一跳地址,Iface 是发送接口,Flags 中的 U 标志表示此条目有效(可以禁用某些 条目),G 标志表示此条目的下一跳地址是某个路由器的地址,没有 G 标志的条目表示目的网络地址是与本机接口直接相连的网络,不必经路由器转发
转发过程例 1:如果要发送的数据包的目的地址是 192.168.56.3
- 跟第一行的子网掩码做与运算得 到 192.168.56.0,与第一行的目的网络地址不符
- 再跟第二行的子网掩码做与运算得 到 192.168.56.0,正是第二行的目的网络地址,因此从 eth1 接口发送出去
- 由于 192.168.56.0/24 正 是与 eth1 接口直接相连的网络,因此可以直接发到目的主机,不需要经路由器转发
转发过程例 2:如果要发送的数据包的目的地址是 202.10.1.2
- 依次和路由表前几项进行对比,发现都不匹配
- 按缺省路由条目,从 eth0 接口发出去,发往 192.168.10.1 路由器
- 由 192.168.10.1 路由器根据它的路由表决定下一跳地址
3.5 IP 分片和组装的具体过程
3.5.1 IP数据报
- 16 位标识(id)
唯一的标识主机发送的报文,如果 IP 报文在数据链路层被分片了,那么每一个片里面的这个 id 都是相同的 - 3 位标志字段
第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到),第二位置为 1 表示禁止分片,这时候如果报文长度超过 MTU,IP 模块就会丢弃报文,第三位表示"更多分片",如果分片了的话,最后一个分片置为 0,其他是 1,类似于一个结束标记 - 13 位分片偏移(framegament offset)
是分片相对于原始 IP 报文开始处的偏移,其实就是在表示当前分片在原报文中处在哪个位置,实际偏移的字节数是这个值除以 8 得到的;因此,除了最后一个报文之外(之前如果都是 8 的整数倍,最后一片的偏移量也一定是 8 的整数倍),其他报文的长度必须是 8 的整数倍(否则报文就不连续了)
注意:片偏移(13 位)表示本片数据在它所属的原始数据报数据区中的偏移量(以 8 字节为单位)
3.5.2 分片与组装的过程
3.5.2.1 分片
1. 检查 MTU 限制
- 当一个 IP 数据报的大小超过了网络的 MTU(最大传输单元)限制时,就需要进行分片。MTU 是数据链路层对 IP 层数据包进行封装时所能接受的最大数据长度
2. 分割数据报
- IP 层将原始的 IP 数据报分割成多个较小的片段
- 对于每个片段,IP 层会设置相应的标识(Identification)、偏移量(Fragment Offset)和标志位(Flags)等字段
- 标识字段用于标识属于同一个数据报的不同分片,确保所有分片能够被正确地重新组装
- 偏移量字段指示了当前分片相对于原始数据报的起始位置,以 8 字节为单位
- 标志位字段包含了 3 个位,其中 MF(More Fragment)位用于指示是否还有更多的分片,DF(Do Not Fragment)位用于指示数据报是否允许进行分片
3. 添加 IP 头部
- 每个分片都会加上自己的 IP 头部,与完整 IP 报文拥有类似的 IP 头结构,但 MF 和 Fragment Offset 等字段的值会有所不同
4. 发送分片
- 分片在传输过程中独立传输,每个分片都有自己的 IP 头部,并且各自独立地选择路由
3.5.2.2 组装
1. 接收分片
- 当目的主机的 IP 层接收到这些分片后,会根据标识字段将属于同一个数据报的所有分片挑选出来
2. 排序与组装
- 利用片偏移字段,IP 层会对属于同一个数据报的分片进行排序
- 当所有的分片都到达并正确排序后,IP 层会将这些分片重新组装成一个完整的 IP 数据报
3. 传递给上层协议
- 组装好的 IP 数据报会传递给上层的协议进行处理
3.5.2.3 分片组装场景
4.数据链路层
用于两个设备(同一种数据链路节点)之间进行传递
4.1 认识以太网
- "以太网" 不是一种具体的网络,而是一种技术标准;既包含了数据链路层的内容,也包含了一些物理层的内容,例如:规定了网络拓扑结构、访问控制方式、传输速率等
- 例如以太网中的网线必须使用双绞线;传输速率有 10M,100M,1000M 等
- 以太网是当前应用最广泛的局域网技术;和以太网并列的还有令牌环网,无线LAN 等
4.2 以太网帧格式
以太网的帧格式如下所示
- 源地址和目的地址是指网卡的硬件地址(也叫 MAC 地址),长度是 48 位,是在网卡出厂时固化的
- 帧协议类型字段有三种值,分别对应 IP、ARP、RARP
- 帧末尾是 CRC 校验码
4.3 认识 MAC 地址
- MAC 地址用来识别数据链路层中相连的节点
- 长度为 48 位, 及 6 个字节,一般用 16 进制数字加上冒号的形式来表示
(例如:08:00:27:03:fb:19) - 在网卡出厂时就确定了,不能修改,mac 地址通常是唯一的(虚拟机中的 mac 地址不是真实的 mac 地址,可能会冲突,也有些网卡支持用户配置 mac 地址)
- IP 地址描述的是路途总体的 起点 和 终点
- MAC 地址描述的是路途上的每一个区间的起点和终点
4.4 认识 MTU
MTU 相当于发快递时对包裹尺寸的限制,这个限制是不同的数据链路对应的物理层,产生的限制
- 以太网帧中的数据长度规定最小 46 字节,最大 1500 字节,ARP 数据包的长度不够 46 字节,要在后面补填充位
- 最大值 1500 称为以太网的最大传输单元(MTU),不同的网络类型有不同的 MTU
- 如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的 MTU 了,则需要对数据包进行分片(fragmentation)
- 不同的数据链路层标准的 MTU 是不同的
4.4.1 MTU 对 IP 协议的影响
由于数据链路层 MTU 的限制,对于较大的 IP 数据包要进行分包
- 将较大的 IP 包分成多个小包,并给每个小包打上标签
- 每个小包 IP 协议头的 16 位标识(id) 都是相同的
- 每个小包的 IP 协议头的 3 位标志字段中,第 2 位置为 0,表示允许分片,第 3 位来表示结束标记(当前是否是最后一个小包,是的话置为 1,否则置为 0)
- 到达对端时再将这些小包,会按顺序重组,拼装到一起返回给传输层
- 一旦这些小包中任意一个小包丢失,接收端的重组就会失败,但 IP 层不会负责重新传输数据
4.4.2 MTU 对 UDP 协议的影响
- 一旦 UDP 携带的数据超过 1472(1500 - 20(IP 首部) - 8(UDP 首部)),那么就会在网络层分成多个 IP 数据报
- 这多个 IP 数据报有任意一个丢失,都会引起接收端网络层重组失败,那么这就意味着,如果 UDP 数据报在网络层被分片,整个数据被丢失的概率就大大增加了
4.4.3 MTU 对于 TCP 协议的影响
- TCP 的一个数据报也不能无限大,还是受制于 MTU. TCP 的单个数据报的最大消息长度,称为 MSS(Max Segment Size)
- TCP 在建立连接的过程中,通信双方会进行 MSS 协商
- 最理想的情况下,MSS 的值正好是在 IP 不会被分片处理的最大长度(这个长度仍然是受制于数据链路层的 MTU)
- 双方在发送 SYN 的时候会在 TCP 头部写入自己能支持的 MSS 值
- 然后双方得知对方的 MSS 值之后,选择较小的作为最终 MSS
- MSS 的值就是在 TCP 首部的 40 字节变长选项中(kind=2)
4.4.4 MSS 和 MTU 的关系
4.4.5 查看硬件地址和 MTU
使用 ifconfig 命令,即可查看 ip 地址 mac 地址 和 MTU
4.5 ARP 协议
虽然我们在这里介绍 ARP 协议,但是需要强调,ARP 不是一个单纯的数据链路层的协议,而是一个介于数据链路层和网络层之间的协议
4.5.1 ARP 协议的作用
ARP 协议建立了主机 IP 地址 和 MAC 地址 的映射关系
- 在网络通讯时,源主机的应用程序知道目的主机的 IP 地址和端口号,却不知道目的主机的硬件地址
- 数据包首先是被网卡接收到再去处理上层协议的,如果接收到的数据包的硬件地址与本机不符,则直接丢弃
- 因此在通讯前必须获得目的主机的硬件地址
4.5.2 ARP 协议的工作流程
- 源主机发出 ARP 请求,询问“IP 地址是 192.168.0.1 的主机的硬件地址是多少”,并将这个请求广播到本地网段(以太网帧首部的硬件地址填 FF:FF:FF:FF:FF:FF 表示广播)
- 目的主机接收到广播的 ARP 请求,发现其中的 IP 地址与本机相符,则发送一个 ARP 应答数据包给源主机,将自己的硬件地址填写在应答包中
- 每台主机都维护一个 ARP 缓存表,可以用 arp -a 命令查看。缓存表中的表项有过期时间(一般为 20 分钟),如果 20 分钟内没有再次使用某个表项,则该表项失效,下次还要发 ARP 请求来获得目的主机的硬件地址
4.5.3 ARP 数据报的格式
- 注意到源 MAC 地址、目的 MAC 地址在以太网首部和 ARP 请求中各出现一次,对于链路层为以太网的情况是多余的,但如果链路层是其它类型的网络则有可能是必要的
- 硬件类型指链路层网络类型,1 为以太网
- 协议类型指要转换的地址类型,0x0800 为 IP 地址
- 硬件地址长度对于以太网地址为 6 字节
- 协议地址长度对于和 IP 地址为 4 字节
- op 字段为 1 表示 ARP 请求,op 字段为 2 表示 ARP 应答
4.5.4 ARP 结合协议的过程
- 注意到源 MAC 地址、目的 MAC 地址在以太网首部和 ARP 请求中各出现一次,对于链路层为以太网的情况是多余的,但如果链路层是其它类型的网络则有可能是必要的
- 硬件类型指链路层网络类型,1 为以太网
- 协议类型指要转换的地址类型,0x0800 为 IP 地址
- 硬件地址长度对于以太网地址为 6 字节
- 协议地址长度对于和 IP 地址为 4 字节
- op 字段为 1 表示 ARP 请求,op 字段为 2 表示 ARP 应答
4.5.5 ARP 欺骗原理
1. 步骤一
2. 步骤二
3. 步骤三
5.NAT
5.1 NAT技术背景
IPv4 协议中,IP 地址数量不充足
NAT 技术当前解决 IP 地址不够用的主要手段,是路由器的一个重要功能
- NAT 能够将私有 IP 对外通信时转为全局 IP,也就是就是一种将私有 IP 和全局 IP 相互转化的技术方法
- 很多学校 家庭 公司内部采用每个终端设置私有 IP, 而在路由器或必要的服务器上设置全局 IP
- 全局 IP 要求唯一,但是私有 IP 不需要,在不同的局域网中出现相同的私有 IP 是完全不影响的
5.2 NAT IP 转换过程
- NAT 路由器将源地址从 10.0.0.10 替换成全局的 IP 202.244.174.37
- NAT 路由器收到外部的数据时,又会把目标 IP 从 202.244.174.37 替换回10.0.0.10
- 在 NAT 路由器内部,有一张自动生成的,用于地址转换的表
- 当 10.0.0.10 第一次向 163.221.120.9 发送数据时就会生成表中的映射关系
5.3 NAPT
那么问题来了,如果局域网内,有多个主机都访问同一个外网服务器,那么对于服务器返回的数据中,目的 IP 都是相同的,那么 NAT 路由器如何判定将这个数据包转发给哪个局域网的主机?
这时候 NAPT 来解决这个问题了,使用 IP+port 来建立这个关联关系
这种关联关系也是由 NAT 路由器自动维护的,例如在 TCP 的情况下,建立连接时,就会生成这个表项,在断开连接后,就会删除这个表项
5.4 NAT 技术的缺陷
由于 NAT 依赖这个转换表,所以有诸多限制
- 无法从 NAT 外部向内部服务器建立连接
- 装换表的生成和销毁都需要额外开销
- 通信过程中一旦 NAT 设备异常,即使存在热备,所有的 TCP 连接也都会断开
6.代理服务器
6.1 NAT 和代理服务器
路由器往往都具备 NAT 设备的功能,通过 NAT 设备进行中转,完成子网设备和其他子网设备的通信过程
代理服务器看起来和 NAT 设备有一点像,客户端像代理服务器发送请求,代理服务器将请求转发给真正要请求的服务器,服务器返回结果后,代理服务器又把结果回传给客户端
那么 NAT 和代理服务器的区别有哪些呢?
- 从应用上讲,NAT 设备是网络基础设备之一,解决的是 IP 不足的问题,代理服务器则是更贴近具体应用,比如通过代理服务器进行翻墙,另外像迅游这样的加速器,也是使用代理服务器
- 从底层实现上讲,NAT 是工作在网络层,直接对 IP 地址进行替换,代理服务器往往工作在应用层
- 从使用范围上讲,NAT 一般在局域网的出口部署,代理服务器可以在局域网做,也可以在广域网做,也可以跨网
- 从部署位置上看,NAT 一般集成在防火墙,路由器等硬件设备上,代理服务器则是一个软件程序,需要部署在服务器
代理服务器是一种应用比较广的技术
- 翻墙:广域网中的代理
- 负载均衡:局域网中的代理
代理服务器又分为正向代理和反向代理.
代购例子
C
花王尿不湿是一个很经典的尿不湿品牌,产自日本;
我自己去日本买尿不湿比较不方便,但是可以让我在日本工作的表姐去超市买了快递给我,此时超市看到的买家是我表姐,我的表姐就是 "正向代理";
后来找我表姐买尿不湿的人太多了,我表姐觉得天天去超市太麻烦,干脆去超市买了一大批尿不湿屯在家里,如果有人来找她代购,就直接把屯在家里的货发出去,而不必再去超市,此时我表姐就是 "反向代理"
正向代理用于请求的转发(例如借助代理绕过反爬虫)
反向代理往往作为一个缓存
6.2 正向代理
6.2.1 概述
- 正向代理(Forward Proxy)是一种常见的网络代理方式,它位于客户端和目标服务器之间,代表客户端向目标服务器发送请求。正向代理服务器接收客户端的请求,然后将请求转发给目标服务器,最后将目标服务器的响应返回给客户端。通过这种方式,正向代理可以实现多种功能,如提高访问速度、隐藏客户端身份、实施访问控制等。
6.2.2 工作原理
- 客户端将请求发送给正向代理服务器
- 正向代理服务器接收请求,并根据配置进行处理,如缓存查找、内容过滤等
- 正向代理服务器将处理后的请求转发给目标服务器
- 目标服务器处理请求,并将响应返回给正向代理服务器
- 正向代理服务器将响应返回给客户端
6.2.3 功能特点
- 缓存功能:正向代理服务器可以缓存经常访问的资源,当客户端再次请求这些资源时,可以直接从缓存中获取,提高访问速度
- 内容过滤:正向代理可以根据预设的规则对请求或响应进行过滤,如屏蔽广告、阻止恶意网站等
- 访问控制:通过正向代理,可以实现对特定网站的访问控制,如限制员工在工作时间访问娱乐网站
- 隐藏客户端身份:正向代理可以隐藏客户端的真实 IP 地址,保护客户端的隐私
- 负载均衡:在多个目标服务器之间分配客户端请求,提高系统的可扩展性和可靠性
6.2.4 应用场景
- 企业网络管理:企业可以通过正向代理实现对员工网络访问的管理和控制,确保员工在工作时间内专注于工作,避免访问不良网站或泄露公司机密
- 公共网络环境:在公共场所如图书馆、学校等提供的网络环境中,通过正向代理可以实现对网络资源的合理分配和管理,确保网络使用的公平性和安全性
- 内容过滤与保护:家长可以通过设置正向代理来过滤不良内容,保护孩子免受网络上的不良信息影响
- 提高访问速度:对于经常访问的网站或资源,正向代理可以通过缓存机制提高访问速度,减少网络延迟
- 跨境电商与海外访问:对于跨境电商或需要访问海外资源的企业和个人,正向代理可以帮助他们突破网络限制,顺畅地访问海外网站和资源
6.3 反向代理
6.3.1 概述
- 反向代理服务器是一种网络架构模式,其作为 Web 服务器的前置服务器,接收来自客户端的请求,并将这些请求转发给后端服务器,然后将后端服务器的响应返回给客户端。这种架构模式可以提升网站性能、安全性和可维护性等
6.3.2基本原理
- 反向代理服务器位于客户端和 Web 服务器之间,当客户端发起请求时,它首先会到达反向代理服务器。反向代理服务器会根据配置的规则将请求转发给后端的 Web 服务器,并将 Web 服务器的响应返回给客户端。在这个过程中,客户端并不知道实际与哪个 Web 服务器进行了交互,它只知道与反向代理服务器进行了通信
6.3.3 应用场景
- 负载均衡:反向代理服务器可以根据配置的负载均衡策略,将客户端的请求分发到多个后端服务器上,以实现负载均衡。这有助于提升网站的整体性能和响应速度,特别是在高并发场景下
- 安全保护:反向代理服务器可以隐藏后端 Web 服务器的真实 IP 地址,降低其被直接攻击的风险。同时,它还可以配置防火墙、访问控制列表(ACL)等安全策略,对客户端的请求进行过滤和限制,以保护后端服务器的安全
- 缓存加速:反向代理服务器可以缓存后端 Web 服务器的响应内容,对于重复的请求,它可以直接从缓存中返回响应,而无需再次向后端服务器发起请求。这可以大大减少后端服务器的负载,提升网站的响应速度
- 内容过滤和重写:反向代理服务器可以根据配置的规则对客户端的请求进行过滤和重写,例如添加或删除请求头、修改请求路径等。这有助于实现一些特定的业务需求,如 URL 重写、用户认证等
- 动静分离:在大型网站中,通常需要将静态资源和动态资源分开处理。通过将静态资源部署在反向代理服务器上,可以直接从反向代理服务器返回静态资源的响应,而无需再次向后端服务器发起请求。这可以大大提升静态资源的访问速度CDN(Content Delivery Network,内容分发网络)就是采用了反向代理的原理
7.内网穿透
7.1 内网打洞
更多推荐
所有评论(0)