我正在使用以下代码尝试将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时发送和接收消息时,似乎问题不在于封闭端口。
有什么想法吗?
答案 0 :(得分:3)
我知道我很晚才到这里,看起来你找到了一个适合你的不同的图书馆,但我认为回复可能对面临这个问题的其他人有所帮助。我是osc.js的开发者,这是您尝试使用的原始库。
首先,作为背景信息,osc.js被分解为两个不同的层:
对于示例代码,您尝试在UDPPort
对象准备好之前发送OSC消息。当您open()
Port
时,它可能需要执行异步操作,例如打开套接字等。因此,它会在端口触发事件(恰当地称为ready
)已全部设定使用。在ready
触发之前,您将无法发送或接收OSC数据包。
因此,对于原始代码,看起来您假设此行是同步的,之后您可以立即调用send()
:
oscUDP.open();
相反,在尝试在ready
上发送消息之前,您只需要监听Port
事件。像这样:
oscUDP.on("ready", function () {
oscUDP.send({
address: "/carrier/frequency",
args: 440
});
});
osc.js Node.js example说明了这种模式。但是当我看到你的问题时,我意识到osc.js自述文件中的示例代码在这方面有点含糊不清。我有improved the event documentation和the 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上提出问题或提出问题。
致以最诚挚的问候,并为您使用该库遇到的麻烦道歉!
答案 1 :(得分:1)
我认为通过UDP发送OSC数据实际上很容易,而不需要除a2r-osc
之外用于编码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);