【问题标题】:Socket.io disconnect event triggering on new connection在新连接上触发 Socket.io 断开事件
【发布时间】:2014-01-08 04:13:50
【问题描述】:

我正在尝试按照书中的教程使用node和socket.io构建聊天服务器和客户端。前端代码如下:

<html>
<head>
    <title>Socket.IO example application</title>
    <style type = "text/css">
    #input {
        width: 200px;
    }
    #messages {
        position: fixed;
        top: 40px;
        bottom: 8px;
        left: 8px;
        right: 8px;
        border: 1px solid #EEEEEE;
        padding: 8px;
    }
    </style>
</head>
<body>
    Your message:
    <input id = "input" type = "text" />
    <div id = "messages"></div>
    <script src = "http://localhost:4001/socket.io/socket.io.js"></script>
    <script type = "text/javascript">
    var messagesElement = document.getElementById('messages');
    var lastMessageElement = null;

    function addMessage (message) {
        var newMessageElement = document.createElement('div');
        var newMessageText = document.createTextNode(message);

        newMessageElement.appendChild(newMessageText);
        messagesElement.insertBefore(newMessageElement, lastMessageElement);
        lastMessageElement = newMessageElement;
    }

    var socket = io.connect('http://localhost:4001');

    socket.on('login', function() {
        var username = prompt('What username would you like to use?');
        socket.emit('login', username);
    });

    socket.on('serverMessage', function (content) {
        addMessage(content);
    });

    function sendCommand(command, args) {
        if(command === 'j') {
            socket.emit('join', args);
        } else {
            alert('unknown command: ' + command);
        }
    }

    function sendMessage(message) {
        var commandMatch = message.match(/^\/(\w*)(.*)/);
        if(commandMatch) {
            sendCommand(commandMatch[1], commandMatch[2].trim());
        } else {
            socket.emit('clientMessage', message);
        }
    }

    var inputElement = document.getElementById('input');

    inputElement.onkeydown = function(keyboardEvent) {
        if(keyboardEvent.keyCode === 13) {
            sendMessage(inputElement.value);
            inputElement.value = '';
            return false;
        } else {
            return true;
        }
    };
    </script>
</body>
</html>

而后端是:

/*jslint node: true */
var httpd = require('http').createServer(handler);
var io = require('socket.io').listen(httpd);
var fs = require('fs');

function handler(req, res) {
    "use strict";
    fs.readFile(__dirname + '/index.html', function (err, data) {
        if (err) {
            res.writeHead(500);
            return res.end('Error Loading index.html');
        }

        res.writeHead(200);
        res.end(data);
    });
}

httpd.listen(4001);

io.sockets.on('connection', function (socket) {
    "use strict";
    socket.on('login', function(username) {
        socket.set('username', username, function (err) {
            if (err) {
                throw err;
            }
            socket.emit('serverMessage', 'Currently logged in as ' + username);
            socket.broadcast.emit('serverMessage', 'User ' + username + ' logged in');
        });
    });

    socket.on('clientMessage', function (content) {
        socket.emit('serverMessage', 'You said: ' + content);
        socket.get('username', function (err, username) {
            if (!username) {
                username = socket.id;
            }
            socket.get('room', function (err, room) {
                if (err) {
                    throw err;
                }
                var broadcast = socket.broadcast,
                    message = content;
                if (room) {
                    broadcast.to(room);
                }
                broadcast.emit('serverMessage', username + ' said: ' + message);
            });
        });
    });

    socket.on('join', function (room) {
        socket.get('room', function (err, oldRoom) {
            if (err) {
                throw err;
            }
            socket.set('room', room, function (err) {
                if (err) {
                    throw err;
                }
                socket.join(room);
                if (oldRoom) {
                    socket.leave(oldRoom);
                }
                socket.get('username', function (err, username) {
                    if (!username) {
                        username = socket.id;
                    }
                    socket.emit('serverMessage', 'You joined room' + room);
                });
                socket.get('username', function (err, username) {
                    if (!username) {
                        username = socket.id;
                    }
                    socket.broadcast.to(room).emit('serverMessage', 'User ' + username + ' joined this room');
                });
            });
        });
    });

    socket.on('disconnect', function() {
        socket.get('username', function (err, username) {
            if (!username) {
                username = socket.id;
            }
            socket.broadcast.emit('serverMessage', 'User ' + username + ' disconnected');
        });
    });

    socket.emit('login');
});

我面临的问题是,每当新用户登录时,所有以前的用户都会在新用户登录之前收到一条消息,说“用户”+随机ID+“断开连接”并且它正常运行。如果新用户在前一个用户登录后快速登录,则不会出现此问题(我猜这与心跳有关)。非常感谢任何帮助,以找出每次新用户登录时都会触发此断开连接事件的原因。谢谢。

【问题讨论】:

  • 我无法重现您提到的问题。

标签: javascript html node.js socket.io


【解决方案1】:

alertprompt 在 javascript 中是阻塞函数,它们会停止浏览器上的所有 javascript 事件。

这就是为什么 socket.io 中的“心脏”停止跳动。

更详细的:

在每个心跳中,服务器都会向客户端发送一个数据包,以检查客户端是活着还是死了,如果客户端没有响应,则服务器认为它已经死了。

解决方案是用异步函数、弹出 div、表单等替换 prompt 函数...

【讨论】:

  • 我假设您的意思是prompt。删除提示并用随机数生成器替换它(现在)似乎可以解决问题。谢谢!
  • @Moriarty 非常感谢您的编辑 :-)。您应该拥有 2K 的声誉,然后您可以在没有 5 个审阅者的情况下进行编辑。
【解决方案2】:

我一直在复制你的代码,并在我的服务器上运行,我找不到你所面临的问题,但是我发现一个问题,当我取消用户名输入窗口时,我的用户名是空的,我发现我的用户 ID 是随机字符串。当我断开连接时,socket.io 会播放这样的消息,

“用户”+随机ID+“断开连接”

【讨论】:

  • 这是预期的行为。您是否尝试过打开一个会话,等待 10 秒再打开另一个会话?第一个用户应该会收到异常消息。
  • 我已经按照你的提示做了,但是我找不到问题,我的浏览器是chrome,你呢。
猜你喜欢
  • 2018-01-28
  • 2011-11-03
  • 2016-09-20
  • 2014-04-03
  • 1970-01-01
  • 2014-03-08
  • 2019-05-01
  • 2012-05-07
  • 1970-01-01
相关资源
最近更新 更多