socket.write() 可否指定 remoteaddress & port?
发布于 11 年前 作者 sipgear 6850 次浏览 最后一次编辑是 8 年前

因为要选择不同客户端发送数据给他,remoteaddress & port 已经存在数据,需要发送时要指定远程的地址和端口(当然,数据库会实时更新客户的地址和端口),查手册socket.write 未提及 指定地址和端口的选项。

13 回复

mysql.query(‘SELECT ipAddressCurrent,remotePortCurrent FROM Device WHERE uniqueID = "’+uid+’"’, function(err, fields) { var res = fields[0]; var clientip = res[‘ipAddressCurrent’]; var clientport = res[‘remotePortCurrent’]; c.write(“test”); });

由于 客户的 ip 和 port 已经 存在数据,发送数据给客户时,想直接用 node net 的模块 发送 socket.write(ipaddress:port,“data”); 查了很多资料未找到,socket.io,可以设置客户端标示,可以发指定的客户(相当于聊天室的私聊),但我想看net可否实现。

var io = require('socket.io').listen(888);
//用于记录所有的客户端
var user_coll = {};
io.sockets.on('connection', function (socket) {
  //客户端连接成功则设置客户端标示
  socket.on('set nickname', function (name) {
    user_coll[name] = socket;
    user_coll[name].set('username', name, function () { user_coll[name].emit('ready'); });
    user_coll[name].on('publicmsg',function(data){
        user_coll[name].get('username',function(err, name){
                var msg ="public msg - "+ name + " say : "+data;
                io.sockets.emit('usermsg',msg);
        });
    })
    user_coll[name].on('privatemsg',function(data){
        //console.log(JSON);return false;
        var jsonData = eval(data);
        user_coll[jsonData.sendTo].get('username',function(err,name){
                var msg ="private msg - "+name +" say : "+jsonData.text;
                user_coll[jsonData.sendTo].emit('usermsg',msg);
        });

    });
  });

});

此socket非彼socket io.sockets.on(‘connection’, function (socket) { 此处的socket ≠ net模块的socket,两者一毛钱关系都没有。。。 要实现楼主所说的效果,要么放弃socket.io自己在socket协议层上做client和server,要么hack进socket.io的代码,同时修改socket.io的server端和client端的代码,以增加相关api。

socket ≠ net模块 我知道,我想用net,实际没有办法再用socket.io,代码是用一个聊天室的。他用socket.io.

是否可以考虑对每个客户端的连接进行标识,标识存在数据库里,要发送到某个客户端时,调用数据库的标识,socket.write(“data”) 给这个客户端。

API for no namespace:

var clients = io.sockets.clients();
var clients = io.sockets.clients('room'); // all users from room `room`
For a namespace

var clients = io.of('/chat').clients();
var clients = io.of('/chat').clients('room'); // all users from room `room`

=========================================================

io.sockets.on('connection',function(socket){

  io.sockets.sockets['nickname'] = socket.id;

        client.on("chat", function(data) {        

           var sock_id = io.sockets.sockets['nickname']
          io.sockets.sockets[sock_id].emit("private", "message");
      });    });

socket.io 有相关的方法。但我想用 node net 模块 。

客户端是浏览器socket.io,服务端想用socket直接发送数据,这样? 但是。。。socket.io本质上是http长连接,socket是tcp协议。除非hack进socket.io的代码,获取本次http连接底层的socket对象,否则根本就没办法进行tcp层面的通讯。经过千难万苦,获得此socket对象,socket.write(‘hello’)发送数据给客户端,客户端根本无法解析:大哥,你说的哪国语言?请你用socket.io协议说话。最终,还是要用socket.io那套玩意,这不是瞎折腾吗。。。

假设能用net模块,那么下一步必须考虑如何用socket.io协议封装数据(具体socket.io协议实现参考rfc 6455),嗯,慢慢折腾吧。谁让客户端已经定死是socket.io呢。

socket.write(‘hello’) 是发给 tcp 的客户端的。

浏览器 连接 http.js, http.js 连接 server.js
server.js 连接 gps 客户端 (tcp通讯)

目前,我已经可以在浏览器器发送数据在server.js里显示(tcp数据来的)。

表达可能不清楚,请见谅。

enter image description here

message->http server(http.js)->tcp server(server.js)->gps client,问题是卡在最后一步, 如何将msg发送给某个gps client,即某个特定remote address &port的连接, 这样?(真心希望能将问题表述的更明确些,猜来猜去真伤脑细胞) 既然能指定客户端的ip&port,那么 server.js至少持有客户端socket对象的引用吧?因此server.js同时接受来自http.js和gps的连接,server.js是router角色?(给出的信息量太少,偶只能猜猜猜。。。)

假使上诉猜测正确,server.js的粗略实现大概如此

var net=require('net');
var user_coll=[];
net.createServer(function(socket){
    /** 此处未考虑所谓的拼包,chunk可能不是一个完整的message**/
    socket.on('data',function(chunk){
        var msg=chunk.toString();
        //parse message to find out which type of client?
        var info=parse(msg);
        if(info.from=='http.js'){ //come from http.js
            var username=info.sendTo;
            //query db by username, fetch ip&port?
            var userInfo=queryUserInfo(username);
            for(var i=0;i<user_coll.length;i++){
                if(userInfo.remoteAddress==user_coll[i].remoteAddress
                   && userInfo.remotePort==user_coll[i].remotePort){
                    user_coll[i].write('forwarded  message');
                }
            }
        }else{ //come from gps client
            if(~user_coll.indexOf(socket)){
                user_coll.append(socket);
            }
            //do more work....
        }
    });
    function dispose(){
        var index=user_coll.indexOf(socket);
        if(~index){
            console.log('%s disconneted',socket.remoteAddress);
            user_coll.splice(index,1);
            socket.removeAllListeners();
        }
    }
    socket.on('end',dispose);
    socket.on('close',dispose);
}).listen(8080);

(聊天数据格式未给出,下半部分编不下去了) 另外就楼主最初问题-能不能socket.write(ipaddress:port,“data”),偶的回答是:NO。node不存在类似的api,当然也能写个类似的方法

function socket_write(ipaddress,port,"data"){
    var socket=net.conenct(port,ipaddress);
    socket.write("data");
}

不过这应该不是楼主的本意吧。

server.js 同时连接gps client和http.js 问题就是要用浏览器发指令给gps client,你的答案应该可以解决问题,衷心感谢。

少了这句:

user_coll.push(socket);

成功根据客户的ID发送数据到客户端,感谢帮助。

回到顶部