【WebSocket&IndexedDB】node+WebSocket&IndexedDB desenvolve uma sala de bate-papo simples

Introdução ao prólogo:

WebSocket é um protocolo para comunicação full-duplex em uma única conexão TCP que o HTML5 começou a fornecer.

Em termos humanos: o WebSocket simplifica a troca de dados entre o cliente e o servidor. Na API WebSocket, o navegador e o servidor só precisam completar um handshake, e uma conexão persistente pode ser criada diretamente entre os dois. e realizar a transmissão bidirecional de dados

Agora, para implementar a tecnologia push, muitos sites usam a pesquisa Ajax. Polling ocorre quando o navegador emite uma solicitação HTTP ao servidor em um intervalo de tempo específico (como a cada 1 segundo) e, em seguida, o servidor retorna os dados mais recentes ao navegador do cliente. Este modelo tradicional traz deficiências óbvias, ou seja, o navegador precisa enviar solicitações continuamente ao servidor. No entanto, as solicitações HTTP podem conter cabeçalhos longos e os dados verdadeiramente válidos podem ser apenas uma pequena parte. Obviamente, isso será um desperdício. A muita largura de banda e outros recursos.

O protocolo WebSocket definido pelo HTML5 pode economizar melhor os recursos do servidor e a largura de banda e permitir mais comunicação em tempo real.

WebSocket:

  • Método comum WebSocket(url): crie um objeto WebSocket e estabeleça uma conexão com o URL especificado
// 创建WebSocket对象并与服务器建立连接
var socket = new WebSocket("ws://example.com");
  • Método comum send(data): enviando dados para o servidor
// 向服务器发送数据
function sendData(data) {
   socket.send(data);
   console.log("发送数据:" + data);
}
  • Método comum close(code, reason): fechar ativamente a conexão WebSocket
// 主动关闭WebSocket连接
function closeConnection() {
   socket.close();
   console.log("关闭WebSocket连接");
}
  • Eventos comuns:: onopenevento acionado quando uma conexão WebSocket é aberta com sucesso
// 连接成功时触发的事件
socket.onopen = function(event) {
   console.log("WebSocket连接已打开");
   // 发送数据示例
   socket.send("Hello, server!");
};
  • Eventos comuns:: onmessageEventos acionados quando uma mensagem é recebida do servidor
// 接收到消息时触发的事件
socket.onmessage = function(event) {
   var message = event.data;
   console.log("收到消息:" + message);
};
  • Eventos comuns:: oncloseevento acionado quando a conexão WebSocket é fechada
// 连接关闭时触发的事件
socket.onclose = function(event) {
   console.log("WebSocket连接已关闭");
};
  • Eventos comuns::  onerrorEventos acionados quando ocorre um erro na conexão WebSocket
// 连接错误时触发的事件
socket.onerror = function(error) {
   console.error("WebSocket错误:" + error);
};

Renderização:

Exibição de código:

index.html

<html>
<head>
    <meta charset="UTF-8">
    <title>webrtc demo</title>
</head>

<body>
    <h1>Websocket简易聊天</h1>
    <div id="app">
        <input id="sendMsg" type="text" />
        <button id="submitBtn">发送</button>
    </div>
</body>
<script type="text/javascript">
    //在页面显示聊天内容
    function showMessage(str, type) {
        var div = document.createElement("div");
        div.innerHTML = str;
        if (type == "enter") {
            div.style.color = "blue";
        } else if (type == "leave") {
            div.style.color = "red";
        }
        document.body.appendChild(div);
    }

    //新建一个websocket
    var websocket = new WebSocket("ws://172.21.2.52:8099");
    //连接建立时触发
    websocket.onopen = function () {
        console.log("已经连上服务器----");
        document.getElementById("submitBtn").onclick = function () {
            // 获取输入的内容
            var txt = document.getElementById("sendMsg").value;
            if (txt) {
                //使用连接发送数据
                websocket.send(txt);
            }
        };
    };
    //连接关闭时触发
    websocket.onclose = function () {
        console.log("websocket close");
    };
    //客户端接收服务端数据时触发
    websocket.onmessage = function (e) {
        var mes = JSON.parse(e.data);   // json格式
        // 渲染
        showMessage(mes.data, mes.type);
    };
</script>

</html>

node.js lembre-se de baixar: dependência nodejs-websocket

var ws = require("nodejs-websocket")
var port = 8099;
var user = 0;

// 创建一个连接
var server = ws.createServer(function (conn) {
    console.log("创建一个新的连接--------");
    user++;
    // 给连接设置昵称属性
    conn.nickname = "user" + user;
    // 给连接设置文件描述符属性
    conn.fd = "user" + user;
    var mes = {};
    // 消息类型为进入聊天室
    mes.type = "enter";
    // 消息内容为进入提示
    mes.data = conn.nickname + " 进来啦"
    // 广播该消息给所有客户端
    broadcast(JSON.stringify(mes));

    //向客户端推送消息
    conn.on("text", function (str) {
        console.log("回复 " + str)
        // 消息类型为普通消息
        mes.type = "message";
        mes.data = conn.nickname + " 说:    " + str;
        broadcast(JSON.stringify(mes));
    });

    //监听关闭连接操作
    conn.on("close", function (code, reason) {
        console.log("关闭连接");
        mes.type = "leave";
        mes.data = conn.nickname + " 离开了"
        broadcast(JSON.stringify(mes));
    });

    //错误处理
    conn.on("error", function (err) {
        console.log("监听到错误");
        console.log(err);
    });
}).listen(port);

function broadcast(str) {
    server.connections.forEach(function (connection) {
        connection.sendText(str);
    })
}

Banco de dados indexado

IndexedDB (banco de dados indexado) é uma solução de armazenamento de banco de dados do lado do cliente fornecida pelo navegador. Ele permite que aplicativos da web armazenem grandes quantidades de dados estruturados no dispositivo do usuário e os consultem e manipulem offline. IndexedDB usa um modelo de armazenamento de objetos, semelhante a um banco de dados relacional, mas não oferece suporte à linguagem de consulta SQL.

  • open(): abre conexão com o banco de dados
let request = window.indexedDB.open("myDatabase", 1);

request.onerror = function(event) {
  console.log("Failed to open database");
};

request.onsuccess = function(event) {
  let db = event.target.result;
  console.log("Database opened successfully");
};
  • createObjectStore(): Cria espaço de armazenamento de objetos
let objectStore = db.createObjectStore("messages", { keyPath: "id", autoIncrement: true });
  • createIndex(): Cria índice
objectStore.createIndex("type", "user", { unique: false });
  • transação(): inicia transação
let transaction = db.transaction(["messages"], "readwrite");
  • objectStore.add(): adiciona dados ao espaço de armazenamento de objetos
let objectStore = transaction.objectStore("messages");
let message = { id: 1, type: "text", data: "Hello World", user: "Alice" };

let request = objectStore.add(message);
request.onsuccess = function(event) {
  console.log("Data added successfully");
};
  • objectStore.get(): obtém dados por chave primária
let objectStore = transaction.objectStore("messages");
  
let request = objectStore.get(1);
request.onsuccess = function(event) {
  let data = event.target.result;
  console.log(data);
};
  • objectStore.getAll(): obtém todos os dados
let objectStore = transaction.objectStore("messages");

let request = objectStore.getAll();
request.onsuccess = function(event) {
  let data = event.target.result;
  console.log(data);
};
  • objectStore.put(): atualiza dados
let objectStore = transaction.objectStore("messages");
let message = { id: 1, type: "text", data: "Hello Updated", user: "Alice" };

let request = objectStore.put(message);
request.onsuccess = function(event) {
  console.log("Data updated successfully");
};
  • objectStore.delete(): exclui dados
let objectStore = transaction.objectStore("messages");
  
let request = objectStore.delete(1);
request.onsuccess = function(event) {
  console.log("Data deleted successfully");
};
  • clear(): Limpa todos os dados no espaço de armazenamento de objetos
let objectStore = transaction.objectStore("messages");

let request = objectStore.clear();
request.onsuccess = function(event) {
  console.log("Object store cleared successfully");
};

Código completo WebSocket mais IndexedDB

WebSocket implementa chat e IndexedDB armazena dados de chat para evitar perda de atualização.

HTML

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>webrtc demo</title>
</head>

<body>
    <h1>Websocket简易聊天</h1>
    <div id="app">
        <input id="sendMsg" type="text" />
        <button id="submitBtn">发送</button>
        <div id="leaveMessage"></div>
        <div id="chat"></div>
    </div>

    <script type="text/javascript">
        var db, transaction, objectStore;
        // 在页面显示聊天内容
        function showMessage(str, type, user = null, state = 1) {
            var div = document.createElement("div");

            var spanStr = document.createElement("span");
            spanStr.innerHTML = str;

            if (user != null) {
                var spanUser = document.createElement("span");
                spanUser.innerHTML = user;
                div.appendChild(spanUser);
            }

            if (type == "enter") {
                div.style.color = "blue";
            } else if (type == "leave") {
                div.style.color = "red";
            }

            div.appendChild(spanStr);
            document.getElementById("chat").appendChild(div);
            if (state == 1) {
                document.getElementById("chat").appendChild(div);
            } else {
                document.getElementById("leaveMessage").appendChild(div);
            }
        }

        // 创建或打开 IndexedDB 数据库
        var request = window.indexedDB.open("chatDB", 1);
        request.onerror = function () {
            console.log("无法打开数据库");
        };

        request.onupgradeneeded = function (event) {
            //  获取到数据库对象 db
            db = event.target.result;
            //  创建名为 "messages" 的对象存储,并指定 "id" 为键路径,并自动递增生成
            objectStore = db.createObjectStore("messages", { keyPath: "id", autoIncrement: true });
            // 创建一个名为 "type" 的索引,用于根据消息类型进行检索,允许重复值
            objectStore.createIndex("type", "user", { unique: false });
            // 创建一个名为 "data" 的索引,用于根据消息内容进行检索,允许重复值
            objectStore.createIndex("data", "data", { unique: false });
            objectStore.createIndex("state", "state", { unique: false });
            objectStore.createIndex("user", "user", { unique: false });
        };

        request.onsuccess = function (event) {
            db = event.target.result;
            // 新建一个websocket
            var websocket = new WebSocket("ws://172.21.2.52:8099");

            // 连接建立时触发
            websocket.onopen = function () {
                console.log("已经连上服务器----");
               
                document.getElementById("submitBtn").onclick = function () {
                    var txt = document.getElementById("sendMsg").value;
                    if (txt) {
                        websocket.send(JSON.stringify(txt));
                    }
                };
                // 给输入框添加键盘按下事件监听器
                document.getElementById("sendMsg").addEventListener("keydown", function (event) {
                    // 检查按下的键是否是回车键(键码为13)
                    if (event.keyCode == 13) {
                        // 取消回车键的默认行为(避免表单提交等操作)
                        event.preventDefault();
                        var txt = document.getElementById("sendMsg").value;
                        if (txt) {
                            websocket.send(JSON.stringify(txt));
                        }
                    }
                });
            };

            // 连接关闭时触发
            websocket.onclose = function () {
                console.log("websocket close");
            };

            // 客户端接收服务端数据时触发
            websocket.onmessage = function (e) {
                var mes = JSON.parse(e.data); // json格式
                // 渲染
                if (mes.state == 0) {
                    showMessage(mes.data, mes.type, mes.user);
                    saveMessage(mes)
                    document.getElementById("sendMsg").value = ''
                } else {
                    showMessage(mes.data, mes.type);
                }
            };

            function saveMessage(message) {
                let transaction = db.transaction(["messages"], "readwrite");
                let objectStore = transaction.objectStore("messages");
                var saveRequest = objectStore.add(message);
                saveRequest.onsuccess = function () {
                    console.log("消息已保存到 IndexedDB");
                };
                saveRequest.onerror = function () {
                    console.log("保存消息时发生错误");
                };
            }

            function loadMessages() {
                // 创建一个只读事务,该事务用于操作名为 "messages" 的对象存储
                transaction = db.transaction(["messages"], "readonly");
                // 获取对 "messages" 对象存储的引用,以便进行后续的操作
                objectStore = transaction.objectStore("messages");
                // 回一个获取所有数据的请求
                var getAllRequest = objectStore.getAll();

                // 在获取数据成功时触发
                getAllRequest.onsuccess = function () {
                    var messages = getAllRequest.result;
                    messages.forEach(function (message) {
                        showMessage(message.data, message.type, message.user, 0);
                    });
                };
            }

            // 页面加载完成后加载聊天记录
            window.onload = function () {
                loadMessages();
            };
        };
    </script>
</body>

</html>

var ws = require("nodejs-websocket")
var port = 8099;
var user = 0;
 
// 创建一个连接
var server = ws.createServer(function (conn) {
    console.log("创建一个新的连接--------");
    user++;
    // 给连接设置昵称属性
    conn.nickname = "user" + user;
    // 给连接设置文件描述符属性
    conn.fd = "user" + user;
    var mes = {};
    // 消息类型为进入聊天室
    mes.type = "enter";
    // 消息内容为进入提示
    mes.data = conn.nickname + " 进来啦";
    mes.state = 1;
    // 广播该消息给所有客户端
    broadcast(JSON.stringify(mes));
 
    //向客户端推送消息
    conn.on("text", function (str) {
        console.log("回复 " + str)
        // 消息类型为普通消息
        mes.type = "message";
        mes.user = conn.nickname + " 说:";
        mes.data = str;
        mes.state = 0;
        broadcast(JSON.stringify(mes));
    });
 
    //监听关闭连接操作
    conn.on("close", function (code, reason) {
        console.log("关闭连接");
        mes.type = "leave";
        mes.data = conn.nickname + " 离开了"
        broadcast(JSON.stringify(mes));
    });
 
    //错误处理
    conn.on("error", function (err) {
        console.log("监听到错误");
        console.log(err);
    });
}).listen(port);
 
function broadcast(str) {
    server.connections.forEach(function (connection) {
        connection.sendText(str);
    })
}

Acho que você gosta

Origin blog.csdn.net/weixin_52479803/article/details/132337529
Recomendado
Clasificación