如何实现类似QQ消息的会话功能?🤔

前言

在面试考题中,如果面试官问关于http协议相关的知识或者直接让你实现一个类似QQ消息的发送,这时候就可以讲到websocket相关的知识了。

那就让我们先来了解一下基础协议相关的技术,再实现会话功能。

1.基础协议与技术

1.1 TCP/IP 协议

TCP/IP 是互联网的基础协议,负责数据的传输。它通过三次握手建立连接,并通过四次挥手断开连接。这种机制确保了数据传输的可靠性。

1.2 HTTP 协议与 Socket

HTTP 协议是应用层协议,通常用于浏览器与服务器之间的通信。它是无状态的,即每次请求都是独立的,服务器不会记住之前的请求。而 Socket 是一种更底层的通信机制,可以实现长连接、消息推送和广播等功能。

1.3 B/S 架构

B/S(Browser/Server)架构是常见的Web应用架构,用户通过浏览器与服务器进行交互。在这种架构下,即时通讯功能通常需要借助 WebSocket 协议来实现。

2. HTTP 与 WebSocket 的区别

先上图表:

2.1 状态性

  • HTTP 是无状态的,每次请求都是独立的,服务器不会记住客户端的状态。
  • WebSocket 是有状态的:服务器会为每个连接保持一个持久的双向通信通道。开发者可以自定义唯一的标识符(如 Socket ID)来管理和区分不同的客户端连接.

2.2 通信方式

  • HTTP 是单向的,客户端发起请求,服务器返回响应,服务器不能主动向客户端发送消息。
  • WebSocket 是双向的,客户端和服务器可以随时向对方发送消息。

2.3 通信模式

  • HTTP 是基于请求-响应的,客户端发起请求后,服务器返回响应,通信结束。
  • WebSocket 是基于事件的,客户端和服务器可以通过事件(如 onmessage)来实时接收消息。

3. WebSocket 服务搭建流程

3.1 基于 HTTP 服务访问聊天页面

首先,我们需要基于 HTTP 服务访问聊天页面。用户通过浏览器访问 http://localhost:3001/,服务器返回一个包含 WebSocket 连接的 HTML 页面。(在这里使用了koa框架和koa-websocket来实现)

js 复制代码
const Koa = require('koa');
const websocket = require('koa-websocket');
const app = websocket(new Koa()); // 开启一个应用实例
const clients = new Set();

app.use(async (ctx, next) => {
    ctx.body = `
    <html>
      <body>
        <div id="messages" style="height: 300px; overflow-y: scroll;"></div>
        <input type="text" id="messageInput" />
        <button onclick="sendMessage()">发送</button>
        <script>
          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>
    `;
});

3.2 WebSocket 连接建立

当用户访问页面后,浏览器会通过 WebSocket 协议向服务器发起连接请求。服务器返回状态码 101 Switching Protocols,表示协议切换成功,后续通信将使用 WebSocket 协议。

js 复制代码
app.ws.use(async (ctx, next) => {
    clients.add(ctx.websocket);
    ctx.websocket.on('message', (message) => {
        for (const client of clients) {
            client.send(message.toString()); // 服务器广播给所有的用户
        }
    });
    ctx.websocket.on('close', () => {
        clients.delete(ctx.websocket);
    });
});

// http 伺服
app.listen(3001,()=>{
    console.log('server is running at port 3001')
})

3.3 消息的发送与接收

在 WebSocket 连接建立后,客户端和服务器可以通过 send 方法发送消息,并通过 onmessage 事件接收消息。服务器可以将接收到的消息广播给所有连接的客户端,实现群聊功能。

3.4 实现效果:

打开两个伺服端口,模拟两个用户之间进行对话,在第一个用户中发送消息,第二个接收,第二个用户发送消息,第一个用户也成功接收

4.执行流程:

当你打开页面并发送一个消息时:

  1. 加载页面

    • 用户访问ws://localhost:3001(或通过其他方式触发Koa应用),Koa应用返回一段HTML代码作为响应。
    • 浏览器解析这段HTML代码,并渲染出一个包含输入框和按钮的简单界面。
  2. 建立WebSocket连接

    • 页面加载完成后,JavaScript代码立即创建一个新的WebSocket实例ws = new WebSocket('ws://localhost:3001'),尝试与服务器建立WebSocket连接。
    • 服务器端通过app.ws.use()注册的中间件监听到新的WebSocket连接请求,并将该连接添加到clients集合中,这标志着WebSocket连接成功建立。
  3. 用户输入消息并点击发送按钮

    • 当用户在输入框内输入文本并点击"发送"按钮后,sendMessage()函数被调用。
    • 函数获取输入框内的值,通过WebSocket对象的send()方法将消息发送至服务器。
  4. 服务器接收并广播消息

    • 服务器端通过监听WebSocket连接的message事件来接收客户端发来的消息。
    • 收到消息后,服务器遍历所有已连接的客户端(存储于clients集合中),并通过每个客户端的send()方法将消息转发给它们,实现消息的广播。
  5. 客户端显示接收到的消息

    • 客户端通过监听WebSocket对象的onmessage事件来处理从服务器接收到的消息。
    • 每当收到新消息时,更新页面上的<div id="messages">元素内容,将新消息追加到已有消息列表的末尾,从而实现实时显示消息的功能。

END

如果觉得哥们的文章对你有帮助,也请给我点个赞吧!

相关推荐
打野赵怀真13 分钟前
render函数中return如果没有使用()会有什么问题?
前端·javascript
Riesenzahn14 分钟前
写一个左中右的满屏布局,左右固定220px,中间自适应并且要优先加载
前端·javascript
Riesenzahn15 分钟前
css在页面上画一个正方形,边长为页面宽度的一半
前端·javascript
拳布离手15 分钟前
Xinference Huggingface常用命令
面试
tommyrunner16 分钟前
Cursor rule文件测试 一秒了解AI行为规则文件
前端·cursor
Lin桐20 分钟前
②Modbus TCP转Modbus RTU/ASCII网关同步采集无需编程高速轻松组网
linux·网络协议·tcp/ip·网络安全·缓存·信息与通信·信号处理
北京_宏哥22 分钟前
《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
java·前端·selenium
Nu1126 分钟前
weakMap 和 weakSet 原理
前端·面试
顾林海29 分钟前
深入理解 Dart 函数:从基础到高阶应用
android·前端·flutter