我正在使用Node.js 0.6.9,我正在尝试发送数据报广播包。代码:
var sys = require('util');
var net = require('net');
var dgram = require('dgram');
var message = new Buffer('message');
var client = dgram.createSocket("udp4");
client.setBroadcast(true);
client.send(message, 0, message.length, 8282, "192.168.1.255", function(err, bytes) {
client.close();
});
运行代码:
$ node test.js
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: setBroadcast EBADF
at errnoException (dgram.js:352:11)
at Socket.setBroadcast (dgram.js:227:11)
at Object.<anonymous> (/home/letharion/tmp/collision/hello.js:25:8)
at Module._compile (module.js:444:26)
at Object..js (module.js:462:10)
at Module.load (module.js:351:32)
at Function._load (module.js:310:12)
at Array.0 (module.js:482:10)
at EventEmitter._tickCallback (node.js:192:41)
一些谷歌搜索reveals“EBADF”的意思是“套接字参数不是有效的文件描述符”。但我对此问题的理解不够充分。
答案 0 :(得分:29)
首先,您似乎无法理解堆栈跟踪的格式,因此在我们转到此处抛出的实际错误之前,请先澄清它。
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
这部分只是内部NodeJS逻辑被阻塞的位置,并在下面列出错误:
接下来是实际的错误堆栈跟踪,它首先在callstack中显示最深位置,因此在堆栈跟踪中向下会带来向上在调用层次结构中,最终将您引导到代码中所有内容开始的位置。
Error: setBroadcast EBADF
at errnoException (dgram.js:352:11)
at Socket.setBroadcast (dgram.js:227:11)
at Object.<anonymous> (/home/letharion/tmp/collision/hello.js:25:8)
at Module._compile (module.js:444:26)
at Object..js (module.js:462:10)
at Module.load (module.js:351:32)
at Function._load (module.js:310:12)
at Array.0 (module.js:482:10)
at EventEmitter._tickCallback (node.js:192:41)
首先它在dgram.js on line 352
中失败,dgram.js
是一个内部node.js模块,用于抽象“低级”代码。行352
位于包含抛出错误的通用逻辑的函数中。
在dgram.js in line 227
调用失败的if检查后,调用包装的本机UDP套接字setBroadcast
方法。
再向上一层,我们最终会通过hello.js
来电25
行client.setBroadcast(true);
文件。
其余的是由hello.js
文件的初始加载产生的更多node.js代码。
node.js在这里包装的本机代码抛出的错误是EBADF
looking this up in conjunction with UDP
给了我们:
EBADF
The socket argument is not a valid file descriptor.
进一步深入到node.js兔子洞,我们最终进入udp wrapper,它包含了实际C实现的uv wrapper,在我们找到的uv包装器中:
/*
* Set broadcast on or off
*
* Arguments:
* handle UDP handle. Should have been initialized with
* `uv_udp_init`.
* on 1 for on, 0 for off
*
* Returns:
* 0 on success, -1 on error.
*/
告诉我们您的套接字尚未初始化的结论。
最后,通过client.bind(8000)
绑定套接字修复了缺少的初始化并使程序运行。
答案 1 :(得分:16)
应该在'listening'事件中调用'setBroadcast'方法:
var socket = dgram.createSocket('udp4');
socket.on('listening', function(){
socket.setBroadcast(true);
});
socket.bind(8000);
答案 2 :(得分:4)
似乎文件描述符仅在bind或on send上创建,并且在setBroadcast之前是必需的。在设置广播之前,您可以在没有参数的情况下调用client.bind()
来绑定到随机端口。不要担心使用随机端口,因为无论如何使用client.send
都会“懒惰”。
var sys = require('util');
var net = require('net');
var dgram = require('dgram');
var message = new Buffer('message');
var client = dgram.createSocket("udp4");
client.bind();
client.setBroadcast(true);
client.send(message, 0, message.length, 8282, "192.168.1.255", function(err, bytes) {
client.close();
});