HTTP 与 WebSocket:构建实时通信应用

168 阅读3分钟

在现代 Web 开发中,实现实时通信是一个常见需求,如在线聊天、实时数据更新等。HTTP 协议在传统的 Web 应用中发挥着重要作用,但它在实时通信方面存在一定局限性,而 WebSocket 协议则弥补了这些不足。本文将结合代码示例,深入探讨 HTTP 与 WebSocket 的区别

屏幕截图 2025-01-03 223816.png

TCP/IP、HTTP 和 WebSocket 基础

TCP/IP 是传输层协议,它通过三次握手建立连接,四次挥手断开连接,为上层应用提供可靠的传输服务。HTTP 是应用层协议,常用于传统的 Web 应用,基于请求 - 响应模式工作。而 WebSocket 同样是应用层协议,支持长连接、消息推送和广播,适用于需要实时通信的场景。

HTTP 与 WebSocket 的区别

1. 状态性

HTTP 是无状态的,每个请求都是独立的,相同的 URL 请求会返回一致的结果,通常使用 cookie 或 authorization 来维护状态。而 WebSocket 是有状态的,每个 Socket 连接会分配一个唯一的标识。

2. 通信方向

HTTP 是单向的,通信流程为 http client -> request -> server -> response -> client,服务器不能主动向客户端发送消息。而 WebSocket 是双向的,服务器可以主动向客户端发送消息。

3. 数据格式

HTTP 是文本协议,传输的数据以文本形式呈现。WebSocket 是二进制协议,能更高效地传输数据。

4. 连接方式

HTTP 是请求响应式的,客户端发送请求,服务器返回响应后连接就会关闭。WebSocket 是长连接式的,连接建立后可以持续进行数据交互。

WebSocket 服务搭建流程

以下是使用 Koa 和 koa - websocket 搭建 WebSocket 服务的代码示例:

const Koa = require('koa');
const websocket = require('koa - websocket');
// 基于 http 协议构建 WebSocket 服务
const app = websocket(new Koa());
// es6 提供新的数据结构,用于存储客户端连接
const clients = new Set();

// 处理 HTTP 请求,返回包含 WebSocket 客户端代码的 HTML 页面
app.use(async ctx => {
  ctx.body = `
  <html>
    <body>
      <div id="messages" style="height: 300px; overflow - y: scroll;"></div>
      <input type="text" id="messageInput" />
      <button onclick="sendMessage()">发送</button>
      <script>
      // html5 新特性,利用 WebSocket 协议和服务器建立连接
      const ws = new WebSocket("ws://localhost:3001");
      ws.onmessage = function(event) {
        const messages = document.getElementById("messages");
        messages.innerHTML += "<div>" + event.data + "<br>";
      }
      function sendMessage() {
        const msg = document.getElementById("messageInput").value.trim();
        ws.send(msg);
      }
      </script>
    </body>
  </html>
  `
})

// 处理 WebSocket 连接
app.ws.use(async (ctx, next) => {
  clients.add(ctx.websocket)
  console.log('-------------')
  // 监听消息事件
  ctx.websocket.on('message', message => {
    for (const client of clients) {
      client.send(message.toString()) // 服务器广播给所有的用户
    }
  })
  // 监听关闭事件
  ctx.websocket.on('close', () => {
    console.log('-----------------------')
    clients.delete(ctx.websocket)
  })
})

// 启动 HTTP 服务
app.listen(3001, () => {
  console.log(`server running on http://localhost:3001`);
})

具体步骤

  1. 基于 HTTP 服务提供页面:客户端通过访问 http://localhost:3001 可以获取包含 WebSocket 客户端代码的 HTML 页面。
  2. 建立 WebSocket 连接:在 HTML 页面中,使用 new WebSocket("ws://localhost:3001") 向服务器端的 WebSocket 服务发起连接。当连接成功时,服务器会返回状态码 101 Switching Protocols,表示协议已从 HTTP 切换到 WebSocket。
  3. 实时通信:连接建立后,客户端和服务器之间可以进行双向通信。客户端通过 ws.send() 方法发送消息,通过 ws.onmessage 事件监听服务器发送的消息。服务器端通过 ctx.websocket.on('message') 监听客户端消息,并通过 client.send() 方法向客户端发送消息。

总结

HTTP 协议适用于传统的 Web 应用,而 WebSocket 协议则为实时通信提供了更好的解决方案。通过上述代码示例,我们可以看到如何基于 Koa 搭建 WebSocket 服务,实现客户端与服务器之间的实时通信。掌握 HTTP 与 WebSocket 的区别和使用方法,有助于开发者根据具体需求选择合适的通信协议。