Nodejs中node+socket.io 数据会重复发多次?
Nodejs中node+socket.io 数据会重复发多次?
var io = require(‘socket.io’).listen(app);
io.configure(function () {
io.set(“transports”, [“xhr-polling”]);
io.set(“polling duration”, 100);
});
io.sockets.on(‘connection’, function (socket) {
socket.broadcast.emit(‘system’, ‘[’ + name + ‘]上线了…’);
socket.on('public message', function (data) {
socket.broadcast.emit('public message', data);
});
socket.on('disconnect', function () {
socket.broadcast.emit('system', '[' + name + ']下线了....');
});
});
客户端:
socket.on('connect', function () {
socket.on('public message', function (data) {
$("#show").append(data);
});
//显示系统广播
socket.on('system', function (data) {
$("#show").append('<span style=color:red>系统信息:' + data + '</span><br/>');
});
});
运行后,打开2个浏览器,先开始正常,打开一个,然后再打开另一个,会正常提示XXX上线了,发信息也没有问题。
但是2个浏览器不做任何操作后(没有关闭浏览器),一段时间,会提示XXX下线了。再过一段时间又自动XXX上线了,而且以后的数据都是重复的,比如发送消息:“你好”,然后另一个浏览器里会显示两边**“你好”**,用这个浏览器回复消息没有问题,会正常显示1条消息。
网上搜了很久,都没找到答案。 是不是
io.set("transports", ["xhr-polling"]);
io.set("polling duration", 100);
设置有问题
这个问题通常与Socket.IO的连接管理有关。xhr-polling
是一种长时间轮询的方式,可能会导致连接不稳定或重复连接。为了确保数据不会重复发送,我们可以尝试使用WebSocket协议,并且优化服务器端和客户端的事件处理逻辑。
示例代码
服务器端代码
var app = require('http').createServer(handler);
var io = require('socket.io')(app);
app.listen(3000);
function handler(req, res) {
res.writeHead(200);
res.end('Welcome to the server');
}
io.on('connection', function(socket) {
var name = socket.handshake.query.name;
socket.broadcast.emit('system', '[' + name + ']上线了...');
socket.on('public message', function(data) {
socket.broadcast.emit('public message', data);
});
socket.on('disconnect', function() {
socket.broadcast.emit('system', '[' + name + ']下线了....');
});
});
客户端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Socket.IO Test</title>
</head>
<body>
<div id="show"></div>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:3000', {
transports: ['websocket'],
query: 'name=Client'
});
socket.on('connect', function() {
console.log('Connected to server');
});
socket.on('public message', function(data) {
$("#show").append('<p>' + data + '</p>');
});
socket.on('system', function(data) {
$("#show").append('<span style="color:red">' + data + '</span><br/>');
});
</script>
</body>
</html>
解释
-
服务器端:
- 使用
io.on('connection')
监听新的连接。 - 在连接时,广播一条系统消息。
- 当接收到
public message
事件时,广播给其他所有连接的客户端。 - 当客户端断开连接时,广播一条下线消息。
- 使用
-
客户端:
- 使用
io.connect
连接到服务器,并传递查询参数name
。 - 监听
connect
事件以确认连接成功。 - 监听
public message
和system
事件,并将消息添加到页面上。
- 使用
优化建议
- 使用
websocket
协议而不是xhr-polling
,因为 WebSocket 提供了更稳定和高效的实时通信。 - 确保客户端每次连接时都正确地处理事件,避免重复发送消息。
通过这些修改,可以减少数据重复发送的情况,并提高整体性能。
你把socket.io客户端升级到最新的0.9x的就好了
这个问题可能是由于Socket.IO的连接和断开机制导致的。xhr-polling
传输方式可能会因为网络延迟或不稳定而频繁地重新建立连接。这会导致你在客户端看到重复的上线和下线通知以及消息重复。
解决方案
你可以尝试以下方法来解决这个问题:
-
避免重复监听事件: 确保每个事件只监听一次。例如,在客户端代码中,确保
connect
事件只监听一次,而不是每次连接时都添加新的监听器。 -
使用更可靠的传输方式: 尝试使用WebSocket或其他更稳定的传输方式,而不是
xhr-polling
。WebSocket是一种持久连接,性能更好,更适合实时通信。 -
检查Session管理: 如果你使用了Session管理,确保每个用户只有一个活跃的Socket连接。
示例代码
服务器端
var io = require('socket.io')(app);
io.on('connection', function(socket) {
console.log('A user connected:', socket.id);
socket.broadcast.emit('system', '[' + name + ']上线了...');
socket.on('public message', function(data) {
socket.broadcast.emit('public message', data);
});
socket.on('disconnect', function() {
socket.broadcast.emit('system', '[' + name + ']下线了....');
});
});
客户端
let socket = io();
socket.on('connect', function() {
console.log('Connected to server');
});
socket.on('public message', function(data) {
$("#show").append(data);
});
socket.on('system', function(data) {
$("#show").append('<span style=color:red>系统信息:' + data + '</span><br/>');
});
socket.on('disconnect', function() {
console.log('Disconnected from server');
});
通过这些调整,可以减少不必要的连接和断开事件,从而避免消息重复发送的问题。