当前位置: 首页 > article >正文

3. 教你用WebSocket构建一个实时聊天应用

系列目录

1.探索WebSocket:实时网络的心跳!

2.WebSocket进阶: 深入探究实时通信的最佳实践与优化技巧

1. 了解聊天室的基本需求

在聊天室中,我们通常需要实现以下功能:
● 用户连接和断开时的通知。
● 用户发送和接收消息的实时更新。
● 管理多用户的消息同步。
● 可扩展的架构以便未来添加更多功能,比如私聊、消息存储等。

2. WebSocket基础: 建立连接

WebSocket提供了一个轻松的API,能够在浏览器和服务器之间建立持久连接。每当用户打开聊天室时,客户端与服务器之间进行WebSocket连接,之后,客户端和服务器之间的通信就不需要重复建立HTTP请求。

基本的WebSocket连接步骤如下:

  1. 客户端发送连接请求
  2. 服务器响应并确认连接
  3. 建立WebSocket连接后,双方可以实时发送和接收消息。

3. 项目架构及代码实现

后端源码: 使用Node.js 搭建 WebSocket服务器
我们可以使用Node.js的ws 库来搭建WebSocket服务器,监听每一个连接的客户端,转发消息到所有用户,从而实现实时消息的广播。
首先,安装ws库:

npm install ws

创建一个服务器文件server.js:

// server.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

const clients = new Set();

wss.on('connection',(ws) = >{
  console.log("A new user connected")
  client.add(ws);

	ws.on('message',(message) => {
    console.log(`Receieve message: ${message}`);
    // 广播信息到所有连接的客户端
    clients.forEach(client = >{
      if (client.readyState == WebSocket.OPEN){
        client.send(message)
      }
    })});
  
  ws.on('close',() = >{
    console.log("A user disconnected.")
		client.delete(ws);
  });
});

console.log("WebSocket server is running on ws://localhost:8080")

在这个例子中,我们创建了一个WebSocket服务器,监听端口8080。当一个新客户端连接时,服务器会将该客户端添加到clients集合中,所有接收到的消息会被广播到每一个已连接的客户端。

前端代码:简单的聊天室页面

创建一个index.html文件,包含基本的页面结构和WebSocket连接的JavaScript代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Chat Room</title>
</head>
<body>
   <h1>Welcome to the Chat Room!</h1>
   <div id="chat">
        <div id="messages"></div>
        <input type="text" id="messageInput" placeholder="Type your message..." />
        <button onclick="sendMessage()">Send</button>
   </div>
  
   <script>
     const ws = new WebSocket('ws://localhost:8080');
     
     ws.open = () =>{
       console.log('Connected to the chat server !');
     };
     
     ws.onmessage = (message) =>{
       const messageDiv= document.getElementById('message');
       const newMessage = document.createElement('div');
       newMessage.textContent = event.data;
       messageDiv.appendChild(newMessage);
     };
     
     ws.onclose = () = {
       console.log('Disconnected from the chat sever.');
     };
     
     function sendMessage (){
       const input = document.getElementById('messageInput');
       if(input.value){
         ws.send(input.value);
         input.value='';
       }
     }
   </script>
</body>
</html>

在这个页面中,我们使用了一个WebSocket连接服务器,并将用户发送的消息广播到所有连接的客户端上。通过监听onmessage事件,页面可以实时更新,显示其他用户发来的新消息。

⚠️注意:WebSocket的文本消息传递的时候默认格式是Binary,我们收到消息之后需要进行解析。

 const data = event.data;

 if (data instanceof Blob) {
      const reader = new FileReader();
      // 异步接收readAsText() 解析后的结果
      reader.onload = function() {
        console.log("Received message:", reader.result);  // 输出转换后的字符串
      };
      reader.readAsText(data);  // 读取 Blob 数据为文本
      console.log("Message type:", data);
 } else {
   console.log("JSON FORMAT");
 }

4. 实现多用户消息格式:带用户名的消息

为了区分不同用户的消息,我们可以在客户端发送消息时附加用户名信息。让用户输入自己的昵称,并在发送消息时附带昵称。

修改前端代码,添加用户名输入:

<input type="text" id="username" placeholder="Enter your name..." />
<button onclick="joinChat()">Join Chat</button>

修改sendMessage函数,使其包含用户名:

function joinChat() {
  const usernameInput = document.getElementById('username');
  if (usernameInput.value) {
    ws.send(JSON.stringify({ type: 'join', username: usernameInput.value }));
  }
}

function sendMessage() {
  const input = document.getElementById('messageInput');
  const username = document.getElementById('username').value;

  if (input.value && username) {
    ws.send(JSON.stringify({ type: 'message', username, content: input.value }));
    input.value = '';
  }
}

修改服务器代码来解析消息格式:

ws.on('message', (data) => {
    const messageData = JSON.parse(data);
    let broadcastMessage = "";

    if (messageData.type === 'join') {
        broadcastMessage = `${messageData.username} joined the chat!`;
    } else if (messageData.type === 'message') {
        broadcastMessage = `${messageData.username}: ${messageData.content}`;
    }

    // 广播给所有客户端
    clients.forEach(client => {
        if (client.readyState === WebSocket.OPEN) {
            client.send(broadcastMessage);
        }
    });
});

在这种方式下,每个用户的消息都将包含用户名,便于区分不同用户的聊天内容。

5. 提升聊天室的用户体验

为了让聊天室的体验更好,可以尝试增加以下功能:

(1) 显示用户的加入/退出通知

每当一个用户连接或断开时,服务器都可以发送通知信息,广播给所有其他在线用户。

(2) 滚动消息视图

在消息框中让新消息自动滚动到最底部,提供更好的聊天体验。可以在每次新消息到来时自动滚动#messages元素:

ws.onmessage = (event) => {
    const messagesDiv = document.getElementById('messages');
    const newMessage = document.createElement('div');
    newMessage.textContent = event.data;
    messagesDiv.appendChild(newMessage);
    messagesDiv.scrollTop = messagesDiv.scrollHeight;  // 滚动到底部
};

(3) 断线重连

在网络波动或服务器重新启动时,自动重新连接WebSocket,使聊天室更加稳定:

ws.onclose = () => {
    console.log('Disconnected from the server. Reconnecting...');
    setTimeout(() => {
        // 重新连接
        connectWebSocket();
    }, 1000);
};
``

http://www.kler.cn/a/373325.html

相关文章:

  • 传智杯 第六届-复赛-C
  • 萤石私有化设备视频平台EasyCVR视频融合平台如何构建农业综合监控监管系统?
  • Couldn‘t apply path mapping to the remote file.
  • Spring Boot 实现文件分片上传和下载
  • SQLI LABS | Less-20 POST-Cookie Injections-Uagent field-error based
  • 模块化沙箱是什么?如何运用到源代码保密中?
  • Chromium 中chrome.fontSettings扩展接口定义c++
  • django中entity.save(using=)的使用
  • 不再输入单号查快递,批量查快递单号信息的新方法,智能排序快递时效并查找时效相同的单号,一站式物流查询解决方案
  • 微服务篇SpringCloud
  • Mysql报错注入之floor报错详解
  • AI学习指南自然语言处理篇-Transformer模型简介
  • 美团2025校招 广告算法工程师 面经
  • Linux基础 -- 文件同步之 rsync 命令的使用
  • golang 高阶函数
  • 各国家的MCC
  • Tomcat异常日志中文乱码怎么解决
  • ELK之路第四步——整合!打通任督二脉
  • 9种 Vuejs 常用事件修饰符与使用指南
  • 《神经网络助力战场车辆及部件损毁识别与评估》
  • 【Moonlight】Sunshine 安装
  • QT——TCP网络调试助手
  • 嵌入式C/C++语言相关知识——C++八股
  • 一个基于.NET8+WPF开源的简单的工作流系统
  • 多重嵌套宏定义带来的错误fatal error: parser recursion limit reached,program too complex
  • 如何配置,npm install 是从本地安装依赖