【问题标题】:Unable to send OSC messages with node's osc package. Port closed error, even though the port on the machine is open无法使用节点的 osc 包发送 OSC 消息。端口关闭错误,即使机器上的端口是打开的
【发布时间】:2016-08-30 09:34:21
【问题描述】:

我正在使用下面的代码尝试将 OSC 消息发送到网络上的计算机。我正在使用一个名为 osc 的包。

我无法向运行 OSC 服务器的机器发送消息,并在尝试发送 OSC 消息时收到以下错误:

Error: Uncaught, unspecified "error" event. (Can't send packets on a closed osc.Port object. Please open (or reopen) this Port by calling open().)

代码

let osc = require('osc');

let oscUDP = new osc.UDPPort({
    remoteAddress: "192.168.1.5",
    remotePort: 8004
});

oscUDP.send({
    address: "/carrier/frequency",
    args: 440
});

oscUDP.open();

如果我将oscUDP.open() 放在send 调用之前,我会得到一个不同的错误:

Error: send EINVAL 192.168.1.5:8004
at Object.exports._errnoException (util.js:1007:11)
at exports._exceptionWithHostPort (util.js:1030:20)
at SendWrap.afterSend [as oncomplete] (dgram.js:402:11)

我在 OSX 上运行 OSCulator 作为服务器。上面的代码存在于不同的机器上。当我在 IP 地址上运行 nmap 时,端口是打开的:

nmap 192.168.1.5 -p 8004

Starting Nmap 6.40 ( http://nmap.org ) at 2016-08-30 08:22 BST
Nmap scan report for 192.168.1.5
Host is up (0.13s latency).
PORT     STATE  SERVICE
8004/tcp open unknown

如果我使用osc-cli,则在运行 OSC 服务器的机器上接收到消息:

osc --host 192.168.1.5:8004 /test 1 2 3

所以看起来问题根本不在于关闭的端口,因为在使用 osc-cli 时会发送和接收消息。

有什么想法吗?

【问题讨论】:

    标签: node.js osc


    【解决方案1】:

    我知道我来晚了,看起来您找到了一个适合您的不同库,但我认为回复可能对面临此问题的其他人有所帮助。我是 osc.js 的开发者,这是您尝试使用的原始库。

    首先,作为背景信息,osc.js 被分解为两个不同的层:

    1. 低级 API,提供用于读取和写入 OSC 消息和捆绑到/从类型化数组的函数。
    2. 更高级别的、基于事件的端口 API,它提供了一组特定于平台的传输对象,从而提供了一种通过 UDP、Web 套接字等协议进行双向通信的简单方法。

    在您的示例代码中,您试图在 UDPPort 对象准备好之前发送一条 OSC 消息。当您open()Port 时,它可能需要执行异步操作,例如打开套接字等。因此,当端口全部设置为使用时,它会触发一个事件(恰当地称为ready) .在ready 触发之前,您将无法发送或接收 OSC 数据包。

    因此,对于您的原始代码,您似乎假设此行是同步的,并且您可以在之后立即调用 send()

    oscUDP.open();
    

    相反,您只需在尝试在Port 上发送消息之前侦听ready 事件。像这样:

    oscUDP.on("ready", function () {
        oscUDP.send({
            address: "/carrier/frequency",
            args: 440
        });
    });
    

    osc.js Node.js example 说明了这种模式。但是当我看到你的问题时,我意识到 osc.js README 中的示例代码在这方面有点模棱两可。我有improved the event documentationthe inline README sample code 在这方面更清楚。很抱歉造成混乱。

    在某些情况下,例如您的情况,高级 API 并不是您所需要的。 osc.js 还提供了将 OSC 数据包轻松编码为Uint8Array 的功能,可以将其转换为 Node.js 缓冲区。因此,您可以通过使用 osc.js 的 osc.writeMessage() 函数来完成与您的解决方案类似的事情。幸运的是,它一直都有很好的记录。这是您的示例,已修改为使用 osc.js 的低级 API:

    const dgram = require('dgram');
    const client = dgram.createSocket('udp4');
    const osc = require('osc');
    
    const HOST = '192.168.1.5';
    const PORT = 8004;
    
    process.on('SIGINT', function() {
      client.close();
    });
    
    let oscNoteMessage = function(note, value) {
      var message = osc.writeMessage({
          address: '/note/' + note,
          args: [
              {
                  type: 'i',
                  value: value
              }
          ]
        });
    
      return Buffer.from(message);
    }
    
    let noteOn = function(note) {
      return oscNoteMessage(note, 1);
    }
    
    let noteOff = function(note) {
      return oscNoteMessage(note, 0);
    }
    
    let send = function(message) {
      client.send(message, PORT, HOST, function(err, bytes) {
        if(err) throw new Error(err);
      })
    }
    
    send(noteOn('c'));
    setTimeout(function() {
      send(noteOff('c'));
    }, 1000);
    

    无论如何,我很高兴您能够提出适用于您的项目的解决方案,我希望此回复对可能遇到类似问题的其他用户有所帮助。当然,请随时在osc.js issue tracker 上提问或提交问题。

    最好的问候,并为您在使用图书馆时遇到的麻烦道歉!

    【讨论】:

      【解决方案2】:

      我认为通过 UDP 发送 OSC 数据实际上非常容易,不需要任何包,除了用于编码 OSC 数据的a2r-osc

      我正在发布解决方案,以防其他人感兴趣:

      const dgram = require('dgram');
      const client = dgram.createSocket('udp4');
      const osc = require('a2r-osc');
      
      const HOST = '192.168.1.5';
      const PORT = 8004;
      
      process.on('SIGINT', function() {
        client.close();
      });
      
      let noteOn = function(note) {
        return new osc.Message('/note/' + note, 'i', 1).toBuffer();
      }
      
      let noteOff = function(note) {
        return new osc.Message('/note/' + note, 'i', 0).toBuffer();
      }
      
      let send = function(message) {
        client.send(message, PORT, HOST, function(err, bytes) {
          if(err) throw new Error(err);
        })
      }
      
      send(noteOn('c'));
      setTimeout(function() {
        send(noteOff('c'));
      }, 1000);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-14
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        相关资源
        最近更新 更多