通过UDP和Node.js

时间:2017-10-19 04:45:52

标签: node.js amazon-ec2 udp osc maxmsp

我正在尝试编写一些简约的客户端 - 服务器代码,以便在不同本地网络上的两台计算机之间传递OSC消息。具体来说,我的最终目标是使用MAX的UDPSend和UDPReceive函数发送和接收Ableton中的MAX补丁,这些函数只是在本地端口上侦听。这是服务器代码,我有Ableton的OSC发送MIDI模块发送到。这正确地接收来自第一台计算机的MAX补丁的输出,一些来自通道的MIDI数据。

var osc = require('osc-min'),
dgram = require('dgram');
var remotes = [];
var FileReader = require('fs');

// listen for OSC messages and print them to the console
var udp = dgram.createSocket('udp4', function(msg, rinfo) {
  try {
    var oscmsg = osc.fromBuffer(msg);
    console.log(oscmsg);
    remotes.forEach(function(remote, index, array) {
        udp.send(msg, 0, oscmsg.length, 10000, remote);
        console.log('Sent OSC message to %s:%d', remote, 10000);
    });
  } catch (err) {
    console.log(err);
  }

});

FileReader.readFile('ips.txt', 'utf8', function(err, data) {
    // By lines
    var lines = data.split('\n');
    for(var line = 0; line < lines.length; line++){
        remotes.push(lines[line]);
    }
});

udp.bind(9998);
console.log('Listening for OSC messages on port 9998');

服务器正确获取如下的OSC消息:

{ address: '/Note1',
args: [ { type: 'integer', value: 60 } ],
oscType: 'message' }

然后,我想将计算机1的消息中继到我在端口9998上的远程服务器上发送给我在端口10000上监听的其他计算机。(该服务器是Amazon EC2 Ubuntu实例。)这些计算机的公共IP位于文件ips.txt。

在接收计算机上(在Windows上测试),我设置了一个Node客户端,通过其公共IP接收数据并将其转发到localhost,以便MAX补丁可以看到它。因此,在此计算机上发送到10000的任何消息都将发送到127.0.0.1:9999。

var osc = require('osc-min'),
    dgram = require('dgram'),
    remote;

// listen for OSC messages and print them to the console
var udp = dgram.createSocket('udp4', function(msg, rinfo) {

  try {
    var oscmsg = osc.fromBuffer(msg);
    console.log(oscmsg);
    send(msg);
  } catch (err) {
    console.log('Could not decode OSC message');
  }

});

function send(oscMessage) {

  udp.send(oscMessage, 0, oscMessage.length, 9999, "127.0.0.1");
  console.log('Sent OSC message to %s:%d', "127.0.0.1", 9999);

}    
udp.bind(10000);
console.log('Listening for OSC messages on port 10000');

问题是,服务器的消息似乎永远不会到达客户端。一旦服务器收到消息,它就会产生输出:

Listening for OSC messages on port 9998
{ address: '/Velocity1',
args: [ { type: 'integer', value: 100 } ],   oscType: 'message' }
Sent OSC message to client-public-ip:10000

但是客户端只是挂起了它的初始监听状态

Listening for OSC messages on port 10000

我认为这可能是我的防火墙的一个问题,我确保通过端口和所涉及的所有应用程序专门启用UDP,没有任何好处。我希望避免使用HTTPRequests。我非常感谢任何建议。

Edit: I created a diagram to help visualize what's supposed to be going on between these three computers. The dashed boxes represent the local network that computer is on (they are all on different networks). I hope this helps a bit.

2 个答案:

答案 0 :(得分:1)

Daniel使用WebSockets的解决方案是正确的。但是,我还需要确保通过DNS名称而不是公共IP地址连接客户端。例如:

const WebSocketClient = require('websocket').client;
const port = process.env.PORT || 3000;
const wsc = new WebSocketClient();
wsc.connect('ws://ec2.compute-1.amazonaws.com:4000/', 'echo-protocol');

相反:

wsc.connect('ws://1.2.3.4:4000/', 'echo-protocol');

有关此问题的更多详细信息here

我还使用了&#39; websocket&#39; npm模块而不是&#39; ws,&#39;但我不确定是否有所作为。

答案 1 :(得分:0)

我发现在不同的局域网之间使用这种方法的最简单方法 WAN用于代理UDP请求,并使用Websockets将它们发送到Echo服务器。这是一个例子:

回应服务器(WAN)

"use strict";

const WebSocket = require('ws');
const port = process.env.PORT || 3000;
const wss = new WebSocket.Server({ port: port });

// Broadcast to all
wss.broadcast = function broadcast(data) {
    wss.clients.forEach(function each(client) {
        if (client.readyState === WebSocket.OPEN) {
            client.send(data);
        }
    });
};

wss.on('connection', function connection(ws, req) {
    const ip = req.connection.remoteAddress;
    console.log('connecting to', ip);

    ws.on('message', function incoming(data) {
        // Broadcast to everyone else.
        wss.clients.forEach(function each(client) {
            if (client !== ws && client.readyState === WebSocket.OPEN) {
                client.send(data);
            }
        });
    });
});

UDP服务器/ WebSocket客户端(本地)

const Buffer = require('buffer').Buffer;
const dgram = require('dgram');
const WebSocketServer = require('ws').Server;

const port = process.env.PORT || 3000;

const wss = new WebSocketServer({port});

//The ip port of the UDP server
var SERVER_IP = '127.0.0.1'
var SERVER_PORT = 11000

wss.on('connection', function(ws) {
    //Create a udp socket for this websocket connection
    let udpClient = dgram.createSocket('udp4');

    //When a message is received from udp server send it to the ws client
    udpClient.on('message', function(msg, rinfo) {
        ws.send(msg.toString());
    });

    //When a message is received from ws client send it to UDP server.
    ws.on('message', function(message) {
        var msgBuff = new Buffer(message);
        udpClient.send(msgBuff, 0, msgBuff.length, SERVER_PORT, SERVER_IP);
    });
});

<强>测试

您可以配置Ableton连接到本地UDP服务器,在此示例中,默认地址类似于udp:// localhost:11000。