2

我正在尝试编写一些极简的客户端-服务器代码来在不同本地网络上的两台计算机之间传递 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 实例。)这些计算机的公共 IP 在文件 ips 中。文本。

在接收计算机上(在 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。我将不胜感激任何建议。

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

4

2 回答 2

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');

关于这个问题的更多细节在这里

我还使用了“websocket”npm 模块而不是“ws”,但我不确定这是否有所作为。

于 2017-11-14T01:17:10.030 回答
0

我发现在不同 LAN 和 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。

于 2017-10-20T04:35:39.513 回答