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

Passing OSC messages between two computers over WAN via UDP and Node.js

我正在尝试编写一些极简主义的客户端-服务器代码,以便在位于不同本地网络上的两台计算机之间传递 OSC 消息。具体来说,我的最终目标是使用 MAX 的 UDPSend 和 UDPReceive 函数在 Ableton 中发送和接收来自 MAX 的补丁,它们只是在本地端口上监听。这是服务器代码,我有 Ableton 的 OSC Send 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 实例。) public 这些计算机的 IP 在文件 ips.txt.

在接收计算机上(在 Windows 上测试),我设置了一个 Node 客户端通过其 public 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。如果有任何建议,我将不胜感激。

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.

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

Echo 服务器(广域网)

"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);
    });
});

测试

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

Daniel 使用 WebSockets 的解决方案是正确的。但是,我还需要确保通过 DNS 名称而不是 public 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

我还使用了 'websocket' npm 模块而不是 'ws,',但我不确定这是否有所不同。