Nodejs WebSocket:同一页面内有的Socket能收到,有的就不行?

Nodejs WebSocket:同一页面内有的Socket能收到,有的就不行?

新手,做了一个很酱油的登录页面。 点击按钮,通过SOCKET向服务器发送信号,服务器验证信号后,会把帐号密码发给登录页面用于比对。 问题出现:通过CMD提供的信息,服务器已经把信息发出去了,可是页面上收不到。 iosocket.on(‘connect’),这个是有效的,因为每次连上服务器,页面会显示“连接” iosocket.on(‘dengluzh’)和iosocket.on(‘denglumm’),这两个收不到服务器发出的信息,因为预设的几个标记都没显示,如“ZH中断”; 我感觉自己的写法没问题,因为这个页面的代码,是我从同一应用下另一个页面上面直接搬过来的,只是换了“信道”罢了。而且那个页面完全正常,Dreamweaver也没报错,运行时服务器也没报错,就是收不到。 现在有点怀疑,会不会是iosocket.on(‘信道’),同一时间能支持的信道数量有限? 自己用同一种方法做出两种结果,相当无语,求帮助 下面是页面对应部分代码:

   var iosocket = io.connect();
		var zh = 'ceshizhuanyongkouling-zhanghao' ;
		var mm = 'ceshizhuanyongkouling-mima';
		iosocket.on('connect',function(){
			$('#zhuangtai').append('<li>连接</li>');	
	
			iosocket.on('dengluzh', function(dengluzh) {
				$('#zhuangtai').append($('<li></li>').text(dengluzh));
				zh = dengluzh;
        $('#zhuangtai').append('<li>ZH中断</li>');			
			});
	        iosocket.on('denglumm', function(denglumm) {
				$('#zhuangtai').append($('<li></li>').text(denglumm));
				mm = denglumm;
        $('#zhuangtai').append('<li>MM中断</li>');	
			if((($('#username').val())==(zh))&&(($('#password').val())==(mm))){
				$('#zhuangtai').append('<li>登录成功</li>');
				alert("登录成功");
				window.location="jieshou.html";
			}else{$('#zhuangtai').append('<li>已停止工作</li>');}	

下面是服务器端对应部分代码:

else if(jsmsg == 'ceshizhuanyongkouling-denglu'){
	console.log('收到信号:',jsmsg);

      .........访问数据库并取得帐号密码...........

			for(var i=0; i<results.length; i++){
			  var firstResult = results[i]; 
			  console.log('id: ' + firstResult['id']+'    username: ' + firstResult['username']);
			  msgzh = firstResult['username'];
			  socket.broadcast.emit('dengluzh',msgzh);
			  msgmm = firstResult['password'];
			  socket.broadcast.emit('denglumm',msgmm);
	          console.log('发送数据:', msgzh,msgmm);
			}	

8 回复

针对你遇到的问题,我将尝试提供一些可能的原因和解决方案。

可能原因

  1. 多个 socket 实例:你在页面中可能创建了多个 socket 实例,导致某些事件监听器没有正确绑定到正确的 socket 实例。
  2. 事件覆盖:可能你在多次加载页面时,重复绑定了事件监听器,导致某些事件被覆盖。
  3. 网络问题或服务器配置:服务器可能没有正确配置广播消息到客户端,或者网络问题导致消息未能到达客户端。

解决方案

1. 确保只有一个 socket 实例

确保在页面中只创建一个 socket 实例,并且所有的事件监听器都绑定到这个实例上。

var iosocket = io.connect();

iosocket.on('connect', function() {
    $('#zhuangtai').append('<li>连接</li>');

    // 移除重复的事件监听器
    iosocket.off('dengluzh');
    iosocket.off('denglumm');

    iosocket.on('dengluzh', function(dengluzh) {
        $('#zhuangtai').append($('<li></li>').text(dengluzh));
        $('#zhuangtai').append('<li>ZH中断</li>');
    });

    iosocket.on('denglumm', function(denglumm) {
        $('#zhuangtai').append($('<li></li>').text(denglumm));
        $('#zhuangtai').append('<li>MM中断</li>');

        if (($('#username').val()) == (dengluzh) && ($('#password').val()) == (denglumm)) {
            $('#zhuangtai').append('<li>登录成功</li>');
            alert("登录成功");
            window.location = "jieshou.html";
        } else {
            $('#zhuangtai').append('<li>已停止工作</li>');
        }
    });
});

2. 检查服务器配置

确保服务器端正确配置了广播消息。你的服务器端代码看起来基本正确,但需要确认是否所有客户端都能接收到这些广播消息。

else if (jsmsg == 'ceshizhuanyongkouling-denglu') {
    console.log('收到信号:', jsmsg);

    // 访问数据库并取得帐号密码
    for (var i = 0; i < results.length; i++) {
        var firstResult = results[i];
        console.log('id: ' + firstResult['id'] + '    username: ' + firstResult['username']);
        var msgzh = firstResult['username'];
        var msgmm = firstResult['password'];

        // 广播消息到所有客户端
        socket.broadcast.emit('dengluzh', msgzh);
        socket.broadcast.emit('denglumm', msgmm);
        console.log('发送数据:', msgzh, msgmm);
    }
}

总结

通过以上步骤,你应该能够解决页面上不同 socket 实例之间消息接收不一致的问题。确保只创建一个 socket 实例,并且正确绑定事件监听器。同时检查服务器端配置,确保消息能够正确广播到所有客户端。


你把iosocket.on('dengluzh', function(dengluzh) {});这些监听的事件不要写到iosocket.on('connect',function(){});这里面试试。

记得 broadcast 有个坑是不会发给自己的, 不知道是不是相关

在这一点上,已经颠来倒去折腾好几回了。。你说的我刚才又试了一遍。。没有效果。。

遇到过这种情况,不过我是服务器端发送,页面接收,应该没有这个问题的。。 主要纠结就是同样的结构,另外一个页面运行正常,这个就无效,还没有报错,就是出不来。。

为什么要把单个用户的帐号密码广播(broadcast)出去?难道用户A要登录,还要先知会用户B/C/D等?就不能正常的socket.emit(‘dengluzh’,msgzh)吗,或者说有非常特殊的需求? 客户端是copy另外一个页面,服务器端的代码也是直接copy过来的?如果是你自己重新写的,那出错有什么好奇怪的。

牛人。。见效了。。 怎么说呢。。我只是想做一个打酱油的登陆界面,能验证数据库里的惟一一个帐号就好。。 至于广播,是因为我找的资料(主要借鉴一个实时聊天程序),里面用的都是broadcast,所以以为是定死了的。。多谢你教我这个。。 关于程序,是我自己东拼西凑捏起来的。。 这次是我第一次用Javascript/Nodejs/Dreamweaver/MySQL/Navicat/TeeChart。。。 再次感谢

根据你提供的代码片段,有几个可能的原因导致某些Socket事件无法触发:

  1. 事件绑定时机:确保iosocket.on('dengluzh')iosocket.on('denglumm')这些事件监听器是在socket连接成功之后绑定的。否则,如果在socket尚未连接时就尝试绑定这些事件,它们将不会生效。

  2. 作用域问题:你的事件监听器是在iosocket.on('connect', function() { ... })内部定义的。这会导致这些事件监听器仅在connect事件触发后才被注册。如果你的socket连接断开后重新连接,需要重新绑定这些事件监听器。

  3. 多个Socket实例:检查是否在同一个页面中存在多个io.connect()调用,从而创建了多个Socket实例。如果确实如此,你需要确保你操作的是正确的Socket实例。

示例代码修正如下:

var iosocket = io.connect();

// 确保事件监听器是在socket连接成功之后绑定的
iosocket.on('connect', function() {
    $('#zhuangtai').append('<li>连接</li>');

    // 在这里绑定事件监听器
    iosocket.on('dengluzh', function(dengluzh) {
        $('#zhuangtai').append($('<li></li>').text(dengluzh));
        $('#zhuangtai').append('<li>ZH中断</li>');
    });

    iosocket.on('denglumm', function(denglumm) {
        $('#zhuangtai').append($('<li></li>').text(denglumm));
        $('#zhuangtai').append('<li>MM中断</li>');

        if (($('#username').val()) === (zh)) && ($('#password').val()) === (mm)) {
            $('#zhuangtai').append('<li>登录成功</li>');
            alert("登录成功");
            window.location = "jieshou.html";
        } else {
            $('#zhuangtai').append('<li>已停止工作</li>');
        }
    });
});

// 如果socket连接断开后需要重新绑定事件监听器
iosocket.on('disconnect', function() {
    // 可以在这里重新绑定事件监听器
});

确保你的服务器代码正确地广播了消息。如果你使用的是Socket.IO,确认服务器端正确地使用了socket.broadcast.emit来广播消息。

回到顶部