Nodejs socket.write() 可否指定 remoteaddress & port?

Nodejs socket.write() 可否指定 remoteaddress & port?

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

15 回复

Node.js Socket.write() 是否可以指定 remoteAddress 和 port?

问题描述

在使用 Node.js 的 net 模块进行网络编程时,我们可能会遇到需要向特定客户端发送数据的情况。假设我们已经有客户端的 remoteAddressport 信息,并希望在发送数据时明确指定这些信息。然而,在查阅 socket.write() 方法的手册时,没有找到直接指定 remoteAddressport 的选项。

解决方案

实际上,socket.write() 方法本身并不支持直接指定 remoteAddressport。这是因为 socket.write() 是用于在已建立连接的套接字上发送数据,而 remoteAddressport 应该在套接字建立连接时指定。

但是,你可以通过创建一个新的套接字连接到目标 remoteAddressport,然后使用 socket.write() 发送数据。以下是一个示例代码:

const net = require('net');

// 假设我们有以下远程地址和端口信息
const remoteAddress = '127.0.0.1';
const remotePort = 8080;

// 创建一个新的套接字连接
const socket = new net.Socket();

// 连接到远程地址和端口
socket.connect(remotePort, remoteAddress, () => {
    console.log(`Connected to ${remoteAddress}:${remotePort}`);
    
    // 在连接成功后发送数据
    const dataToSend = 'Hello, client!';
    socket.write(dataToSend);
});

// 处理错误
socket.on('error', (err) => {
    console.error(`Socket error: ${err.message}`);
});

// 监听数据接收事件
socket.on('data', (data) => {
    console.log(`Received data: ${data.toString()}`);
});

// 监听连接关闭事件
socket.on('close', () => {
    console.log('Connection closed');
});

总结

虽然 socket.write() 本身不支持直接指定 remoteAddressport,但你可以通过创建一个新的套接字连接来实现这一功能。在连接成功后,你可以使用 socket.write() 发送数据到指定的远程地址和端口。


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发送数据到客户端,感谢帮助。

在 Node.js 中,socket.write() 方法用于向已连接的套接字写入数据。socket.write() 并不直接支持指定 remoteAddressremotePort,因为该方法默认就是将数据发送到已经建立连接的对端。

为了实现向特定的远程地址和端口发送数据,你需要创建一个新的套接字连接,并在连接成功后使用 socket.write() 方法发送数据。以下是一个示例代码来说明这一过程:

const net = require('net');

// 定义目标地址和端口
const remoteAddress = '127.0.0.1';
const remotePort = 8080;

// 创建一个新的 TCP 套接字
const clientSocket = new net.Socket();

// 当套接字连接成功时触发
clientSocket.connect(remotePort, remoteAddress, () => {
    console.log(`Connected to ${remoteAddress}:${remotePort}`);

    // 向连接的目标地址和端口发送数据
    const dataToSend = "Hello, world!";
    clientSocket.write(dataToSend);
});

// 监听错误事件
clientSocket.on('error', (err) => {
    console.error('Socket error:', err);
});

// 监听关闭事件
clientSocket.on('close', () => {
    console.log('Connection closed');
});

在这个例子中,我们首先定义了目标地址 (remoteAddress) 和端口 (remotePort)。然后,我们创建了一个新的 TCP 套接字 (clientSocket) 并调用 connect() 方法来连接到指定的远程地址和端口。一旦连接成功,我们就可以使用 socket.write() 方法来发送数据。

请注意,在实际应用中,你需要根据实际情况来处理连接失败、错误和其他边缘情况。

回到顶部