面试官问SSE和WebSocket的区别?看这篇就够了(含心跳机制详解)

0 阅读5分钟

最近在复习计算机网络和 LLM 相关技术时,我突然意识到一个很有意思的现象:现在的 AI 聊天大多用的是 SSE,但提到真正的实时互动,还得看 WebSocket

为了搞懂这玩意儿,我手写了一个简易版的聊天室。今天就把我的学习笔记、代码实现,还有那些让人头秃的协议对比,一次性全掏出来!


🤔 为什么 HTTP 不适合聊天?

咱们先聊聊背景。作为前端,我们最熟悉的是 HTTP 协议。

HTTP 就像是一个“高冷”的客服

  • 你问一句(Request),它答一句(Response)。
  • 答完就挂电话(短连接),下次想问得重新拨号。

如果你想做一个聊天室,用 HTTP 怎么办?只能靠轮询

// 每隔 1 秒问一次服务器:“有新消息吗?有新消息吗?”
setInterval(() => {
  fetch('/api/messages').then(...)
}, 1000);

这太蠢了,对吧?性能差,延迟高,服务器都要被问烦了。

SSE 呢?SSE 适合 LLM 那种“流式输出”(我一次提问,它一直吐字),它是单向的。但聊天是双向的,我要发,你也要发。

所以,我们需要一个能建立“长连接”、双方都能主动说话的协议——WebSocket


💡 WebSocket:一次握手,终身相伴

WebSocket 是 HTML5 提供的一种在单个 TCP 连接上进行全双工通讯的协议。

  • 全双工:就像打电话,双方都可以同时说话,不需要等对方说完。
  • 长连接:一旦建立,除非主动断开,否则一直连着。

📝 核心代码逻辑拆解

这里我用 Koa + koa-websocket 来实现。为了让大家看得更清楚,我把代码拆成三个关键步骤来讲。

步骤一:搭建舞台(服务端初始化)

首先,我们需要让 Koa 具备处理 WebSocket 的能力,并准备一个“花名册”来记录所有连进来的用户。

javascript

编辑

const Koa = require('koa');
const websocket = require('koa-websocket');

// 1. 初始化 Koa 并赋予 WebSocket 能力
const app = websocket(new Koa());

// 2. 准备一个 Set 集合,用来存储所有连接的客户端
// 为什么用 Set?因为我们要保证连接对象的唯一性
const clients = new Set();

步骤二:派发请柬(处理 HTTP 请求)

WebSocket 连接通常是从一个网页开始的。所以,我们需要一个普通的 HTTP 中间件,返回给浏览器一个包含聊天界面的 HTML 页面。

javascript

编辑

// 3. 处理普通 HTTP 请求:返回我们的聊天页面
app.use(async (ctx) => {
    ctx.body = `
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>WebSocket Chat</title>
    </head>
    <body>
       <div id="messages" style="height:300px;overflow-y:scroll; border:1px solid #ccc;"></div>
        <input type="text" id="messageInput" placeholder="输入消息..."/>
        <button onclick="sendMessage()">发送</button>
        <script>
            // 核心在这里:前端建立 WebSocket 连接
            // 注意协议是 ws:// 而不是 http://
            const ws = new WebSocket('ws://localhost:3000/ws');
            
            // 监听服务器发来的消息
            ws.onmessage = function(event){
                const messageDiv = document.getElementById('messages');
                messageDiv.innerHTML += '<div>' + event.data + '</div>';
            }
            
            function sendMessage(){
                const input = document.getElementById('messageInput');
                ws.send(input.value); // 发送消息
                input.value = '';
            }
        </script>
    </body>
    </html>
    `
})

步骤三:建立专线(处理 WebSocket 连接)

这是最关键的一步。当浏览器执行了 new WebSocket() 后,服务器会通过 app.ws.use 捕获到这个连接请求。

这里我们主要做三件事:登记用户监听消息广播消息

javascript

编辑

// 4. 处理 WebSocket 连接
app.ws.use(async (ctx) => {
    // A. 登记:将当前连接加入集合
    clients.add(ctx.websocket);
    console.log('当前在线人数:', clients.size);

    // B. 监听:当收到某人的消息时
    ctx.websocket.on('message', message => {
        // C. 广播:把这条消息发给“花名册”里的每一个人
        for(const client of clients){
            client.send(message.toString());
        }
    });

    // D. 离场:监听断开连接,把人从花名册里删掉
    ctx.websocket.on('close', () => {
        clients.delete(ctx.websocket);
        console.log('有人离开了...');
    });
})

app.listen(3000, () => {
    console.log('🚀 服务器启动,请访问 http://localhost:3000');
});

运行效果:
打开浏览器访问 localhost:3000,你可以打开好几个标签页,在一个标签页发消息,所有标签页都会实时收到消息!这就是广播

image.png


📊 一张表看懂 HTTP、SSE 与 WebSocket

为了面试(408 计算机网络)和工作,这三个协议的区别必须门儿清:

特性HTTPSSEWebSocket
连接方式短连接 (请求-响应)长连接 (单向推送)长连接 (双向通讯)
通讯方向客户端发起服务端 -> 客户端客户端 <-> 服务端
适用场景网页加载、API 请求AI 流式输出、股票行情聊天室、即时游戏、协作编辑
数据格式文本/JSON/二进制仅限文本 (text/event-stream)二进制帧/文本帧
  • SSE:适合“我不动,你推给我”的场景(比如 LLM 打字机效果)。
  • WebSocket:适合“你一句我一句”的场景。

❤️ 心跳机制:长连接的“异地恋”哲学

既然 WebSocket 是长连接,那就面临一个现实问题:网络是不稳定的

路由器重启、手机进电梯、防火墙拦截……都可能导致连接“静默断开”。这时候,客户端以为连着,服务器以为断了,这就尴尬了。

怎么解决?—— 心跳机制

这就好比异地恋的情侣

你们不能一直打电话(开销太大),但必须定期确认对方还在。

  • 客户端:“宝,你在吗?”(Ping)
  • 服务端:“在呢,活着呢。”(Pong)

如果客户端发了 Ping,过了 30 秒还没收到 Pong,那就判定为“分手”(连接断开),然后触发重连机制

代码逻辑示意:

// 客户端
setInterval(() => {
    if(ws.readyState === WebSocket.OPEN){
        ws.send(JSON.stringify({type: 'ping'}));
    }
}, 30000); // 每30秒问候一次

// 服务端
ws.on('message', (msg) => {
    const data = JSON.parse(msg);
    if(data.type === 'ping'){
        ws.send(JSON.stringify({type: 'pong'})); // 秒回
    }
});

📌 总结

今天我们从 HTTP 的局限性出发,手搓了一个基于 Koa 的 WebSocket 聊天室,顺便复习了 SSE 和心跳机制。

划重点:

  1. HTTP 是“一问一答”,WebSocket 是“双向奔赴”。
  2. SSE 适合流式输出(AI),WebSocket 适合即时通讯(Chat)。
  3. 心跳机制是长连接保活的关键,防止“假死”连接。

希望这篇文章能帮你搞定 WebSocket!如果觉得有用,记得点个赞 👍,我们下期见!