Skip to content

TCP/IP 与 HTTP ​

本篇定位

覆盖握手挥手、TCP/UDP、HTTPS、状态码和 HTTP 版本。

高频面试题 ​

Q1:TCP 为什么三次握手、四次挥手? ​

我的答案:

结论先说:三次握手是为了双方都确认彼此的收发能力正常,并同步初始序列号;四次挥手是因为 TCP 全双工,两个方向要各自关闭。

第一次,客户端发 SYN,带初始序号 seq=x,表示"我想连你,我的起始序号是 x"。第二次,服务端回 SYN+ACK,ack=x+1、seq=y,表示"我收到了,也同意连你,我的起始序号是 y"。第三次,客户端再发 ACK,ack=y+1,表示"我也收到你的序号了"。三次之后双方都知道对方能收能发。为什么不是两次?因为如果只有两次,历史重复的 SYN 会让服务端白等资源——第三次握手就是让服务端确认客户端此刻真的在线。

挥手要四次是因为全双工:主动方发 FIN 表示"我不发了",被动方先回 ACK,但此时被动方可能还有数据要发,等它发完再发自己的 FIN,主动方再回 ACK。所以 FIN 和 ACK 不能合并,要分四次。

最后一个关键点:主动关闭方发完最后一个 ACK 后要进 TIME_WAIT,等 2MSL(最大报文生存时间的两倍)。原因是要保证最后一个 ACK 能到达对方(丢了对方会重发 FIN),同时让本次连接的所有旧报文在网络中消亡,避免影响下一条同四元组的连接。线上如果 TIME_WAIT 过多,可以开 tcp_tw_reuse,但不要轻易开 tw_recycle(NAT 场景会出问题)。


Q2:TCP 和 UDP 区别及场景? ​

我的答案:

结论:TCP 是面向连接、可靠、字节流的协议;UDP 是无连接、尽力而为、数据报的协议。

第一,TCP 面向连接,要先三次握手,断开要四次挥手;UDP 发数据前不需要握手,直接往 socket 里写就行,所以延迟低、开销小。

第二,TCP 保证可靠:有序列号、确认应答、超时重传、滑动窗口、拥塞控制(慢启动、拥塞避免、快重传、快恢复),数据按序到达、不丢不重。UDP 不保证,丢了就丢了、后发的可能先到,可靠性由应用层自己做。

第三,TCP 是字节流,没有报文边界,会粘包;UDP 是一条一条的数据报,有边界,发多大收多大。

第四,开销上 TCP 头部至少 20 字节,还要维护连接状态、拥塞窗口;UDP 头部只有 8 字节。

场景上:要求可靠传输的用 TCP,比如 HTTP/HTTPS、SSH、MySQL、Redis、文件下载、邮件;要求低延迟、能容忍少量丢包的用 UDP,比如 DNS 查询(53 端口)、视频会议、直播、游戏实时位置、QUIC/HTTP3、NTP。现在很多新场景(WebRTC、游戏)干脆在 UDP 上自己做一层可靠传输,就是为了既快又可控。


Q3:HTTPS 加密过程? ​

我的答案:

结论:HTTPS = HTTP + TLS,核心思想是用非对称加密协商出一个对称密钥,之后全程对称加密,再用证书证明服务器身份。

简化流程(TLS 1.2 为例):第一,客户端 Client Hello,带上支持的 TLS 版本、加密套件列表、一个随机数 client random。第二,服务端 Server Hello,选定加密套件,给另一个随机数 server random,然后把自己的证书(含公钥、域名、有效期、CA 签名)一起发回来。第三,客户端验证证书:先看证书链能不能追溯到本机信任的根 CA,再看域名是否匹配、是否过期、有没有被吊销(CRL/OCSP)。验证通过后,客户端生成一个 pre-master secret,用服务器公钥加密发过去。第四,双方用 client random + server random + pre-master secret 各自算出会话密钥 session key。第五,之后所有业务数据都用这个对称密钥(AES-GCM 之类)加密传输。

TLS 1.3 把这个过程压缩到 1-RTT,甚至 0-RTT,握手更快,并且废弃了 RSA 密钥交换、固定用 ECDHE 前向 secrecy——意思是即使服务器私钥以后泄露,历史抓包也解不开,这就是前向安全。

为什么不全用非对称?因为非对称太慢,不适合传大量数据;为什么不全用对称?因为对称密钥怎么安全地交给对方是个死结。所以两者结合:非对称解决"密钥怎么安全传",对称解决"数据怎么快加密"。


Q4:常见 HTTP 状态码? ​

我的答案:

结论:状态码分 5 类,3 位数字,第一位是大类。我按类背。

2xx 成功:200 OK 正常返回;201 Created 新建成功(POST);204 No Content 成功但没返回体,常用于 DELETE。

3xx 重定向:301 Moved Permanently 永久重定向,浏览器会缓存,换域名、HTTP 跳 HTTPS 用;302 Found 临时重定向,每次都重新请求;304 Not Modified 协商缓存命中,浏览器带 If-None-Match/If-Modified-Since,服务器资源没变就回 304,浏览器用本地缓存。注意 301/302 历史上 POST 会被改成 GET,303/307/308 专门规范了这一点,307/308 保持方法不变。

4xx 客户端错误:400 Bad Request 请求参数/格式错;401 Unauthorized 没登录或 token 失效,要认证;403 Forbidden 认证了但没权限;404 Not Found 路由/资源不存在;405 Method Not Allowed 方法不对;429 Too Many Requests 触发限流。

5xx 服务端错误:500 Internal Server Error 后端代码抛异常;502 Bad Gateway 反向代理(Nginx)拿不到后端响应,后端挂了或端口不通;503 Service Unavailable 服务暂时不可用,一般是过载或维护;504 Gateway Timeout 代理等后端超时了。

面试里最常被追问的是 502 和 504 的区别:502 是"连都没连上/后端直接拒了",504 是"连上了但后端处理太慢超时"。排查思路我在 Nginx 那题展开。


相关链接 ​