无论是正常的 HTTP、SSE 还是 WebSocket,它们在最底层都依赖于 TCP 协议
接触了SSE之后,突然想到一个问题,HTTP连接依赖TCP,TCP包含三次握手和四次挥手,那SSE呢,服务器不间断的传输数据,那他还挥手吗,什么时候挥手呢,然后做了一下深入了解,在此记录一下
TCP 的基石:三次握手与四次挥手
TCP 是一种“面向连接”的协议,它要求在发数据前必须先确认“你我都在线”。
三次握手 (建立连接) —— 确认彼此的收发能力
想象你在和 DeepSeek 语音通话:
- 第一次握手 (SYN):你说:“喂,你能听到我说话吗?”(客户端发送同步序列号)。
- 第二次握手 (SYN+ACK):DeepSeek 回:“我能听到,你能听到我吗?”(服务器确认客户端请求,并发送自己的同步信号)。
- 第三次握手 (ACK):你说:“我也能听到,那我们要开始聊了。”(客户端确认服务器信号)。 连接建立成功!
四次挥手 (断开连接) —— 优雅地再见
由于 TCP 是全双工的(两边都能同时说话),所以关闭时需要两边都同意:
- 第一次挥手 (FIN):你说:“我说完了,挂了啊。”
- 第二次挥手 (ACK):DeepSeek 说:“收到,但我这还有最后一点数据发完再挂。”(此时你进入半关闭状态)。
- 第三次挥手 (FIN):DeepSeek 说:“我也发完了,挂了。”
- 第四次挥手 (ACK):你说:“好嘞,拜拜。”(经过一段时间确认无误后,连接彻底关闭)。
1.HTTP(1.1)连接机制
在现代 HTTP/1.1 中,默认开启了 Keep-Alive (持久连接)。
- 机制:以前 HTTP/1.0 是“一问一答就挥手”。现在为了快,握手一次后,水管保持接通。
- 流程:握手 ->请求 1 -> 响应 1 - > 请求 2 -> 响应 2 ->... ->挥手。
- 局限性:必须是“一请求一响应”。服务器不能主动说话,且响应没回来之前,水管是占用的(线头阻塞)
2.SSE (Server-Sent Events) 的机制
SSE 本质上就是利用了持久化 HTTP 连接的“特殊长连接”。
- 握手阶段:完全走标准 HTTP 三次握手。
- 传输阶段:客户端发一个标准 GET 请求。服务器返回 200 OK,但在 Header 里标记 Content-Type: text/event-stream。关键点:服务器永远不执行四次挥手中的第一次挥手。它保持连接开启,不断地往这个响应体里 write 数据。
- 断开:通常由服务器发完数据后主动 res.end() 触发挥手,或浏览器关闭页面触发。
它的核心: 只要不挥手,水管就一直通,服务器就能一直滴水。
3.WebSocket 的机制
WebSocket 是 HTTP 的“近亲”,但它在握手后会**“脱离”** HTTP。
- 握手阶段 (Upgrade):客户端先发一个 HTTP 请求,带上 Upgrade: websocket 头部。服务器回一个 101 Switching Protocols。协议转换:一旦握手成功,双方就不再讲 HTTP 语言了,而是改用更简单的 Binary Frame (二进制帧) 协议。
- 传输阶段:真正的双工:任何时候,服务器和客户端都可以同时向对方发消息。数据帧:数据被切成极小的帧,开销比 HTTP 小得多(HTTP 有厚重的 Header,WebSocket 帧头只有几个字节)。
- 挥手:有专门的 Close Frame(关闭帧)来触发断开。