1. TCP/IP协议栈核心机制与面试高频问题
TCP/IP协议栈是计算机网络面试中必问的核心知识点,我当年准备面试时花了整整两周时间啃这块硬骨头。先说一个实际案例:有次面试官让我解释"为什么TCP建立连接需要三次握手,而断开连接却要四次挥手?"这个问题看似简单,但能考察候选人对协议设计的深层理解。
1.1 三次握手的精妙设计
三次握手的过程就像古代两国建交的仪式:第一次握手(SYN)相当于A国派使者送出玉玺,第二次握手(SYN+ACK)是B国送回玉玺并附上自己的国玺,第三次握手(ACK)则是A国确认收到国玺。这个设计解决了三个关键问题:
序列号同步:双方通过交换初始序列号(ISN)来确保数据有序传输。比如客户端发送SYN包携带seq=100,服务端回应时ack=101,这就建立了明确的序号对应关系。
防止历史连接干扰:假设旧的SYN包因网络延迟后到达,服务端会返回SYN+ACK,客户端通过对比序列号发现不匹配,立即发送RST终止连接。这就是为什么不能简化为两次握手。
资源分配时机:服务端在第三次握手完成后再分配连接资源,避免了SYN Flood攻击导致的资源耗尽。我曾用Python模拟过攻击场景:
# SYN Flood攻击模拟代码 import socket target_ip = "192.168.1.1" target_port = 80 while True: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect_ex((target_ip, target_port)) # 故意不完成握手1.2 四次挥手的必要性
断开连接时,TCP需要分别关闭两个独立的数据通道。就像两个人通话结束时的道别:
- 客户端发送FIN表示说完话(第一次挥手)
- 服务端先回复ACK确认收到(第二次挥手)
- 等服务端说完话再发送FIN(第三次挥手)
- 客户端最后确认(第四次挥手)
这里的关键在于TCP的全双工特性——两个方向的数据传输是独立的。当客户端发送FIN时,只是关闭了客户端→服务端的数据通道,服务端可能还有数据要发送。
1.3 流量控制与拥塞控制
流量控制就像调节水龙头大小,通过滑动窗口机制实现。接收方在ACK包中通告自己的接收窗口(rwnd),比如:
ACK seq=101, ack=201, rwnd=3000表示"我已收到200字节,还能再收3000字节"。
拥塞控制则是应对网络拥堵的智能算法,包含四个核心阶段:
- 慢启动:窗口从1开始指数增长
- 拥塞避免:达到阈值后线性增长
- 快重传:收到3个重复ACK立即重传
- 快恢复:重传后不重置窗口大小
2. HTTP/HTTPS协议深度解析
2.1 HTTP协议演进史
HTTP/1.1的管道化(pipelining)特性允许连续发送多个请求,但仍有队头阻塞问题。就像超市收银台前排队的顾客,前一个人卡住后面都得等着。
HTTP/2通过二进制分帧和流的多路复用彻底解决了这个问题:
HEADERS帧(流ID=1) --> GET /index.html DATA帧(流ID=1) --> <html>... HEADERS帧(流ID=3) --> GET /style.css不同流的帧可以交错发送,互不阻塞。
2.2 HTTPS握手过程详解
HTTPS的TLS握手就像秘密会面的确认流程:
- 客户端发送"Client Hello"(支持的加密套件+随机数A)
- 服务端返回"Server Hello"(选择的加密套件+随机数B)+证书
- 客户端验证证书,生成预主密钥(Premaster Secret)并用证书公钥加密
- 双方通过随机数A、B和预主密钥生成会话密钥
这里有个关键点:前两次握手是明文传输的,因此TLS 1.3通过预共享密钥(PSK)将握手缩短到1-RTT,甚至0-RTT。
2.3 状态管理机制对比
Cookie和Session的区别就像会员卡和后台记录:
- Cookie存储在客户端,有大小限制(4KB),可能被篡改
- Session存储在服务端,更安全但会增加服务器负载
现代JWT(JSON Web Token)采用签名机制结合了两者优点:
Header.Payload.Signature eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c3. 网络安全防护实战
3.1 常见攻击与防御
SYN Flood攻击就像恶意的电话骚扰:攻击者不断拨号但不说话,占用接线员资源。防御方案包括:
- SYN Cookie技术:服务端不保存半连接状态,而是通过加密算法生成序列号
# SYN Cookie生成算法示例 def syn_cookie(src_ip, src_port, dst_ip, dst_port, secret): hash = HMAC(secret, [src_ip, src_port, dst_ip, dst_port]) return (hash[0:4] & 0x7fffffff) # 保留31位避免溢出- 连接速率限制:如Linux的iptables规则
iptables -A INPUT -p tcp --syn -m limit --limit 1/s -j ACCEPT3.2 CSRF与XSS防御
CSRF攻击示意图:
恶意网站 → 用户浏览器 → 银行网站(携带用户cookie)防御措施:
- 同源检测:验证Referer头
- Token验证:表单中嵌入随机Token
- SameSite Cookie属性:限制第三方Cookie使用
XSS防御则需要输入输出双重过滤:
// 使用DOMPurify库过滤HTML const clean = DOMPurify.sanitize(userInput);4. 网络性能优化策略
4.1 TCP优化参数
Linux系统调优示例:
# 增大TCP窗口大小 echo "net.ipv4.tcp_window_scaling = 1" >> /etc/sysctl.conf # 启用快速打开(TFO) echo "net.ipv4.tcp_fastopen = 3" >> /etc/sysctl.conf sysctl -p4.2 HTTP/2服务端推送
Nginx配置示例:
server { listen 443 ssl http2; location / { http2_push /style.css; http2_push /app.js; } }4.3 CDN加速原理
CDN节点选择算法:
- 通过DNS解析获取边缘节点IP
- 基于Anycast技术路由到最近节点
- 实时监控节点负载进行动态调度
5. 典型面试场景模拟
5.1 问题:解释TIME_WAIT状态
回答要点:
- 持续时间:2MSL(默认60秒)
- 存在意义:
- 确保最后一个ACK到达对端
- 让网络中残留包失效
- 生产问题:高并发短连接可能导致端口耗尽
- 解决方案:
# 启用TIME_WAIT重用 echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
5.2 问题:HTTPS如何避免中间人攻击
回答框架:
- 证书链验证(信任锚)
- 密钥交换算法(ECDHE)
- 签名机制(RSA/ECDSA)
- HSTS头强制HTTPS
Strict-Transport-Security: max-age=63072000; includeSubDomains
5.3 问题:TCP和UDP如何选择
决策树:
需要可靠传输? → 是 → TCP 低延迟优先? → 是 → UDP 需要多播? → 是 → UDP实际案例对比:
- 视频会议:UDP+QUIC(如WebRTC)
- 文件传输:TCP+重传机制
- DNS查询:UDP+超时重试