You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何调用encryptClient()后Socket.IO陷入无限递归循环?

解决Socket.IO添加encryptClient()后出现的递归溢出错误

未将encryptClient()函数加入emit方法前,Socket.IO运行完全正常,但添加后执行时触发以下递归溢出错误并陷入循环:

Uncaught InternalError: too much recursion
isBinary is-binary.js:20
hasBinary is-binary.js:36
hasBinary is-binary.js:45
hasBinary is-binary.js:45
hasBinary is-binary.js:45
hasBinary is-binary.js:45
hasBinary is-binary.js:45
hasBinary is-binary.js:45
hasBinary is-binary.js:45
hasBinary is-binary.js:45
hasBinary is-binary.js:45

相关代码

index.html

<script >
    var socket = io();

    var messages = document.getElementById('messages');
    var form = document.getElementById('form');
    var input = document.getElementById('input');

    form.addEventListener('submit', function (e) {
        e.preventDefault();
       // var cipherText = encryptClient();
        
        if (input.value) {
            socket.emit('chat message', encryptClient());  
            input.value = '';
            console.log("encrypted message sent")
        }
    });

    socket.on('chat message', function (msg) {
        var item = document.createElement('li');
        item.textContent = msg;
        messages.appendChild(item);
        window.scrollTo(0, document.body.scrollHeight);
    });
</script>

index.js

const cwd = process.cwd();
const express = require(cwd + '/node_modules/express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const port = process.env.PORT || 3000;

app.use(express.static(cwd));

app.get('/', (req, res) => {
    res.sendFile('/index.html');
});

io.on('connection', (socket) => {
    socket.on('chat message', msg => {
        io.emit('chat message', msg);
    });
});

http.listen(port, () => {
    console.log(`Socket.IO server running at http://localhost:${port}/`);
});

ClientEncrypt.js(已用browserify打包)

window.encryptClient = () => {
    //document.getElementById("welcomeText").innerHTML = "poop";
    console.log("started");
    var CryptoJS = require("crypto-js");
    
    //var plainText = "Test";
    var plainText = document.getElementById("input").value;
    if(plainText == ''){
        console.log("Error, encrypt called while empty")
        return null;
    }
    var secretKey = "zdvB5oTxhVjxuFLBd8UJOOvNH3yton8POErBOza6n0z5OSKrNwniqA7mD5SNFTTZ";
    var cipherText = CryptoJS.AES.encrypt(plainText, secretKey);

    console.log("Encrypted Message: " + cipherText);
    //document.getElementById("welcomeText").innerHTML = cipherText;

    var decryptedPlainText = CryptoJS.AES.decrypt(cipherText, secretKey);
    console.log("Decrypted Message: " + decryptedPlainText.toString(CryptoJS.enc.Utf8));

    return cipherText;
}

问题原因与解决方案

原因

CryptoJS.AES.encrypt()返回的不是普通字符串,而是一个包含循环引用的CryptoJS对象。Socket.IO在序列化这个对象时,会递归遍历其内部属性,触发无限递归,最终导致栈溢出错误。

解决步骤

  1. 修改加密函数的返回值:在ClientEncrypt.js中,将返回的cipherText转为字符串格式:
// 替换原return语句
return cipherText.toString();
  1. 接收端处理(可选):如果需要在客户端解密消息,接收时将字符串转回CryptoJS可处理的格式即可:
socket.on('chat message', function (msg) {
    // 解密示例(需确保客户端有CryptoJS依赖)
    var secretKey = "zdvB5oTxhVjxuFLBd8UJOOvNH3yton8POErBOza6n0z5OSKrNwniqA7mD5SNFTTZ";
    var decrypted = CryptoJS.AES.decrypt(msg, secretKey);
    var plainText = decrypted.toString(CryptoJS.enc.Utf8);
    
    var item = document.createElement('li');
    item.textContent = plainText; // 或直接显示加密后的msg
    messages.appendChild(item);
    window.scrollTo(0, document.body.scrollHeight);
});

这样修改后,Socket.IO发送的是普通字符串,不会触发递归遍历对象的逻辑,即可解决递归溢出问题。

内容的提问来源于stack exchange,提问作者BHughes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 06:55:54