通过UDP和Node.js通过WAN在两台计算机之间传递OSC消息

我试图写一些简约的客户端服务器代码来传递两台不同本地networking上的计算机之间的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' } 

然后我想通过端口9998将计算机1的消息中继到远程服务器上的其他端口为10000的计算机(服务器是Amazon EC2 Ubuntu实例)。这些计算机的公共IP位于文件ips 。文本。

在接收计算机上(在Windows上testing),我设置了一个Node客户端,通过其公共IP接收数据,并将其中继到本地主机,以便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。 我非常感谢任何build议。

编辑:我创build了一个图表来帮助可视化这三台电脑之间应该发生的事情。 虚线框表示计算机所在的本地networking(它们都在不同的networking上)。 我希望这个能有一点帮助。

我发现在不同局域网和广域网之间工作的最简单方法是代理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); }); }); 

testing

你可以configurationAbleton连接到本地UDP服务器,在这个例子中默认的地址是udp:// localhost:11000。

Daniel的解决scheme使用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'); 

关于这个问题的更多细节。

我也使用'websocket'npm模块来代替'ws',但我不确定这是否有所作为。