【WebSocket&IndexedDB】node+WebSocket&IndexedDB desarrolla una sala de chat simple

Introducción al prólogo:

WebSocket es un protocolo para comunicación full-duplex en una única conexión TCP que HTML5 comenzó a proporcionar.

En términos humanos: WebSocket simplifica el intercambio de datos entre el cliente y el servidor. En la API de WebSocket, el navegador y el servidor solo necesitan completar un protocolo de enlace y se puede crear una conexión persistente directamente entre los dos y realizar una transmisión de datos bidireccional.

Ahora, para implementar la tecnología push, muchos sitios web utilizan la tecnología de encuesta Ajax. El sondeo se produce cuando el navegador emite una solicitud HTTP al servidor en un intervalo de tiempo específico (por ejemplo, cada segundo) y luego el servidor devuelve los datos más recientes al navegador del cliente. Este modelo tradicional tiene desventajas obvias, es decir, el navegador necesita enviar solicitudes continuamente al servidor, pero las solicitudes HTTP pueden contener encabezados largos y los datos reales válidos pueden ser solo una pequeña parte, lo que obviamente será un desperdicio. mucho ancho de banda y otros recursos.

El protocolo WebSocket definido por HTML5 puede ahorrar mejor los recursos del servidor y el ancho de banda y permitir una mayor comunicación en tiempo real.

WebSocket:

  • Método común WebSocket(url): cree un objeto WebSocket y establezca una conexión con la URL especificada
// 创建WebSocket对象并与服务器建立连接
var socket = new WebSocket("ws://example.com");
  • Método común send(data): enviar datos al servidor.
// 向服务器发送数据
function sendData(data) {
   socket.send(data);
   console.log("发送数据:" + data);
}
  • Método común close(code, reason): cerrar activamente la conexión WebSocket
// 主动关闭WebSocket连接
function closeConnection() {
   socket.close();
   console.log("关闭WebSocket连接");
}
  • Eventos comunes: onopenevento que se activa cuando se abre correctamente una conexión WebSocket
// 连接成功时触发的事件
socket.onopen = function(event) {
   console.log("WebSocket连接已打开");
   // 发送数据示例
   socket.send("Hello, server!");
};
  • Eventos comunes: onmessageeventos que se activan cuando se recibe un mensaje del servidor
// 接收到消息时触发的事件
socket.onmessage = function(event) {
   var message = event.data;
   console.log("收到消息:" + message);
};
  • Eventos comunes: oncloseEvento que se activa cuando se cierra la conexión WebSocket
// 连接关闭时触发的事件
socket.onclose = function(event) {
   console.log("WebSocket连接已关闭");
};
  • Eventos comunes:  onerrorEventos desencadenados cuando ocurre un error en la conexión WebSocket
// 连接错误时触发的事件
socket.onerror = function(error) {
   console.error("WebSocket错误:" + error);
};

Representación:

Visualización de código:

índice.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 recuerda descargar: dependencia 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);
    })
}

DB indexado

IndexedDB (base de datos indexada) es una solución de almacenamiento de bases de datos del lado del cliente proporcionada por los navegadores. Permite que las aplicaciones web almacenen grandes cantidades de datos estructurados en el dispositivo del usuario y los consulten y manipulen sin conexión. IndexedDB utiliza un modelo de almacenamiento de objetos, similar a las bases de datos relacionales, pero no admite el lenguaje de consulta SQL.

  • open(): Abrir conexión a la base de datos
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(): crea espacio de almacenamiento de objetos
let objectStore = db.createObjectStore("messages", { keyPath: "id", autoIncrement: true });
  • createIndex(): Crear índice
objectStore.createIndex("type", "user", { unique: false });
  • transacción(): iniciar transacción
let transaction = db.transaction(["messages"], "readwrite");
  • objectStore.add(): agrega datos al espacio de almacenamiento 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(): Obtener datos por clave principal
let objectStore = transaction.objectStore("messages");
  
let request = objectStore.get(1);
request.onsuccess = function(event) {
  let data = event.target.result;
  console.log(data);
};
  • objectStore.getAll(): obtiene todos los datos
let objectStore = transaction.objectStore("messages");

let request = objectStore.getAll();
request.onsuccess = function(event) {
  let data = event.target.result;
  console.log(data);
};
  • objectStore.put(): actualizar datos
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(): eliminar datos
let objectStore = transaction.objectStore("messages");
  
let request = objectStore.delete(1);
request.onsuccess = function(event) {
  console.log("Data deleted successfully");
};
  • clear(): borra todos los datos en el espacio de almacenamiento de objetos
let objectStore = transaction.objectStore("messages");

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

WebSocket más código completo IndexedDB

WebSocket implementa el chat e IndexedDB almacena datos del chat para evitar pérdidas por actualización.

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>

nodo

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);
    })
}

Supongo que te gusta

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