由于“EBADF”,Node.js,dgram.setBroadcast(flag)失败

时间:2012-02-11 18:42:03

标签: node.js

我正在使用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”的意思是“套接字参数不是有效的文件描述符”。但我对此问题的理解不够充分。

3 个答案:

答案 0 :(得分:29)

首先,您似乎无法理解堆栈跟踪的格式,因此在我们转到此处抛出的实际错误之前,请先澄清它。

node.js Stacktrace

的格式
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来电25client.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();
});