🌐 IP地址与网络基础
IP地址就像快递单上的地址,是网络中设备的"门牌号"。IPv4地址有32位,最多约43亿个。过去我们学A、B、C类地址划分,现在更常用的是CIDR方式。
为了支持更多设备,网络被分为**广域网(WAN)**和**局域网(LAN)**。公网IP用于WAN,私有IP用于LAN。通过NAT技术,一个公网IP可以代表多个私有设备,大大扩展了地址容量。
家庭网络通常使用`192.168.xx.xx`这样的C类私有地址,所以你家的IP大多是192.168开头的。
🔁 NAT与内网穿透
IPv4地址不够用?NAT(网络地址转换)路由器让整个内网共享一个公网IP,极大节省地址资源。
普通NAT只改IP地址,容易冲突;更常用的是**NAPT**,同时修改IP和端口号。
NAT也带来一个问题:公网无法直接访问内网服务。**内网穿透**技术解决了这个问题,让你在公司也能访问家里的电脑。
📡 ICMP与网络连通性
我们常用`ping`测试网络是否通畅,它其实是基于**ICMP协议**的封装。ICMP是网络层协议,不是传输层。
ICMP报文分为**查询报文**和**差错报文**,用Wireshark抓包可以看到详细信息。注意:`ping`不通不代表网络完全不可用,有些设备会关闭ICMP响应,但不影响TCP/UDP通信。
🛠️ 网络设备演进史
-
两台电脑用网线直连即可通信。
-
设备多了用**集线器**,但它会广播,效率低。
-
**交换机**(数据链路层)能学习MAC地址,减少广播。
-
互联网规模下,交换机不够用,**路由器**(网络层)登场,通过网段定位路径。
现在家里很少用集线器和独立交换机,路由器通常集成了交换机功能,电脑接上路由器,再通过光猫就能上网。
🔌 Socket与TCP/UDP
**Socket**是一套网络连接的数字标识符。
-
`sock`在内核,`socket fd`在用户空间。
-
内核通过`sock`结构体实现网络传输,用户通过`socket fd`操作网络。
-
服务端用**四元组**(源IP、源端口、目标IP、目标端口)区分客户端连接。
**TCP**有重传、流量控制、滑动窗口、拥塞控制等机制,保证可靠传输,但速度相对慢。
**UDP**无连接、无复杂控制,通常更快。但有些项目(如《王者荣耀》的KCP)在UDP上实现自定义重传机制。
> 注意:UDP+重传时,若数据包太大且未分段,丢一个分片就要重传整个包,这时TCP反而可能更快。
🔄 TCP连接管理:挥手、自连接与同时打开
-
四次挥手中,FIN包可能由主动close或进程被杀触发。
-
大量`FIN_WAIT_2`状态?可能是对端不close。
-
`close()`关闭收发,`shutdown()`可单独关闭一方。
-
挥手可能合并为三次,甚至出现**自连接**(自己连自己,挥手两次)。
-
两个客户端也能直接建立连接,称为**TCP同时打开**(四次握手)。
这些场景虽不常用,但能帮你理解TCP的灵活性。
🧠 TCP连接队列:半连接 vs 全连接
-
`listen()`时会创建两个队列:**半连接队列(SYN队列)** 和 **全连接队列(Accept队列)**。
-
第三次握手前连接在半连接队列,完成后移到全连接队列。
-
`accept()`只是从全连接队列取一条连接,不参与握手过程。
-
半连接队列是哈希表,全连接队列是链表。
-
队列满时可能丢包或发RST,可设置`tcp_syncookies`应对SYN Flood攻击。
客户端没有这两个队列,但有一个全局哈希表管理连接,支持自连接和同时打开。
🚨 RST复位报文:异常连接的"杀手"
-
RST是TCP标志位,用于异常关闭连接。
-
应用层读/写时才会感知到RST,常见错误如"Connection reset by peer"。
-
RST发出后不需确认,丢了对方可能不知道,但重传或keepalive会触发新RST。
-
序列号不在窗口内的RST会被静默丢弃。
-
故意构造合法RST可实现**RST攻击**(请勿模仿)。
🧩 粘包问题:TCP与UDP的差异
-
TCP是字节流,无边界,可能粘包。
-
接收端需根据应用层协议解析消息边界。
-
关闭Nagle算法不能根本解决粘包。
-
UDP是数据报,有明确边界,无粘包问题。
-
IP层会分片,但不管内容,也不存在粘包。
> TCP发10次,收可以分100次读;UDP发10次,收必须分10次收。
🧩 分段 vs 分片
-
TCP分段用**MSS**,IP分片用**MTU**。
-
TCP分段后,IP层通常不用再分片,重传也只需传小段。
-
MSS根据MTU计算,可动态调整。
-
IPv6禁止中间设备分片,只能在端到端进行。
-
**PMTU发现**可探测路径MTU,TCP可靠,UDP可能丢包。
🚪 连接不存在的端口
-
连接一个IP正确但端口不存在的主机,对方会回复RST。
-
如果目标机器有防火墙,可能收不到RST,只能不断重试SYN。
🌐 HTTP与Nginx
-
HTTP状态码:200成功,4xx客户端错误,5xx服务端错误。
-
Nginx做反向代理和负载均衡,客户端不关心后端是谁。
-
后端服务崩溃时,Nginx可能收到RST,返回**502 Bad Gateway**。
-
502是Nginx生成的,后端可能无日志,需查Nginx日志或监控服务状态。
🔁 HTTP vs RPC
-
TCP是无边界的数据流,HTTP和RPC都是在TCP之上定义的应用层协议。
-
RPC是一种调用方式,gRPC、Thrift是具体实现。
-
RPC不一定基于TCP。
-
过去HTTP用于B/S,RPC用于C/S,现在界限模糊。
-
很多RPC性能优于HTTP/1.1,但HTTP/2.0也有很强竞争力。
🔄 WebSocket:全双工通信利器
-
TCP是全双工,但HTTP/1.1是半双工。
-
WebSocket支持全双工,适合服务端主动推送(如网页游戏)。
-
WebSocket与Socket无关,只是名字像。
-
它先通过HTTP握手升级,之后使用WebSocket格式通信。
📬 DHCP:动态获取IP地址
-
插上网线后,计算机会通过DHCP获取IP、掩码、网关等。
-
四个阶段:Discover → Offer → Request → ACK。
-
曾连过的话可跳过Discover。
-
DHCP是应用层协议,基于UDP(支持广播)。
-
获取IP后会发无偿ARP,确认无冲突才使用。
🔐 HTTPS与TLS
-
非对称加密基于大数取模和欧拉定理,公钥加密只有私钥能解。
-
HTTPS = HTTP + TLS,主流是TLS 1.2。
-
TLS握手四次,涉及两对非对称密钥(服务器 + CA)。
-
理解三个随机数(Client/Server Random、Pre-Master Secret)有助于掌握流程。
🌍 DNS:高并发的分布式系统
-
DNS是层次化、缓存丰富的分布式系统,设计思路值得借鉴。
-
通过DHCP或手动配置获取DNS服务器。
-
根域服务器有13组IP,国内有很多镜像,用户可就近访问。
-
DNS可用UDP或TCP,小于512字节用UDP。
🛣️ 任播技术
-
同一个IP对应多个服务器,路由器选最近路径。
-
任播可实现负载均衡和高可用,但不能替代Nginx。
🔒 SSH:安全的远程登录
-
早期用telnet,明文传输不安全。
-
SSH分两阶段:交换信息生成对称密钥 → 加密通信。
-
支持密码登录和公钥登录(推荐后者)。
-
使用时注意检查服务器指纹,避免中间人攻击。
🔁 回环地址与本地地址
-
`127.0.0.1`是回环地址,`localhost`默认解析到它。
-
ping回环地址或本机IP都不会出网卡,数据在本地网络栈处理。
-
服务监听`0.0.0.0`时,可用`127.0.0.1`或本机IP访问。
🧭 路由与ECMP
-
路由器根据目标IP匹配路由表,选最优路径。
-
默认网关用于无匹配时。
-
多条路径成本相同时,称为等价路径。
-
**ECMP**可同时利用多条路径,提高带宽利用率。
-
同一连接的数据包走同一路径,减少乱序。
📦 网络丢包:不可避免但可管理
-
网络链路长,丢包难免。
-
TCP重传保证传输层可靠,但应用层需自己实现业务确认。
-
接口延迟高或失败时,可用`ping`或`mtr`检查丢包。
🖥️ Unix Domain Socket:本机进程通信利器
-
用于本机进程间通信,不走网络栈,性能更高。
-
比localhost通信更轻量,适合高性能服务。
🎚️ QoS:服务质量调度
-
QoS通过优先级调度保证网络体验。
-
IP头中的DSCP字段标记服务质量等级。
-
拥塞时TCP通常优先级高于UDP,但音视频等UDP流也可能被优先。
-
基于UDP的应用可换端口、加前向纠错,规避QoS限制。
📦 序列化与反序列化
-
常见方案:XML、JSON、Protobuf、Thrift。
-
XML适合复杂结构和可读性要求高的场景。
-
JSON轻量、易读,广泛使用。
-
Protobuf、Thrift性能高,适合大数据和性能敏感场景。
🔍 Protobuf详解
-
数据以键值对形式组织:tag + value。
-
tag包含字段序号和类型信息。
-
数组通过重复tag表示。
-
数字用Varints编码压缩。
-
嵌套结构体像"俄罗斯套娃"。
-
默认值不序列化,节省空间。
💾 文件存储与CDN
-
文本数据存MySQL,缓存用Redis。
-
视频、图片等文件用OSS存储,CDN加速。
-
CDN回源时可能比直连更慢。
-
CDN优势:就近调度 + 缓存重复文件。
-
内网服务+低频访问文件可不接CDN。
🤔 遗留思考题
> `mtr`命令是如何知道到达目标地址路径上每一跳路由器的IP地址的?