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

Let*_*ion 16 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();
});
Run Code Online (Sandbox Code Playgroud)

运行代码:

$ 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)
Run Code Online (Sandbox Code Playgroud)

一些谷歌搜索显示 "EBADF"意味着"套接字参数不是有效的文件描述符".但我对这个问题的理解不够充分.

Ivo*_*zel 32

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

node.js Stacktrace的格式

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
Run Code Online (Sandbox Code Playgroud)

这部分只是内部NodeJS逻辑被阻塞的位置,并在下面输出错误:

实际的错误堆栈跟踪如下,它显示了最深的调用堆栈第一的位置,所以要在堆栈跟踪,为您带来在调用层次结构,最终导致你在你的代码的地步,一切都开始了.

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)
Run Code Online (Sandbox Code Playgroud)

首先它失败了dgram.js on line 352,dgram.js是一个内部node.js模块抽象"低级"代码.Line 352位于包含抛出错误的通用逻辑的函数中.

在调用dgram.js in line 227失败的if检查之后调用了包装本机UDP套接字setBroadcast方法的调用.

再向上一层,我们最终会在您的hello.js文件25client.setBroadcast(true);通话.

其余的是由hello.js文件的初始加载产生的更多node.js代码.

实际的错误

node.js在这里包装的本机代码抛出的错误EBADF UDP我们一起查看这个错误:

EBADF
    The socket argument is not a valid file descriptor. 
Run Code Online (Sandbox Code Playgroud)

通过去进一步下降到node.js的兔子洞,我们在结束了UDP封装,其封装了UV包装的实际C实现,在紫外线的包装,我们发现:

/*
* 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.
*/
Run Code Online (Sandbox Code Playgroud)

引导我们得出您的套接字尚未初始化的结论.

最后,通过client.bind(8000)修复缺少的初始化来绑定套接字并使程序运行.

  • 那是一个绝对好的答案!非常感谢你.我会创造一个奖励只是为了奖励它,但似乎我不能.我想这是因为问题是新的. (2认同)
  • 我在SO上看到的最佳答案之一. (2认同)
  • 虽然广泛涉及node.js stacktrace部分,但应更新答案以指示client.setBroadcast(true);。和client.send(...)函数只能在bind回调中调用(即,我们不应该假定bind是同步的) (2认同)

Den*_*hin 18

应该在'listen'事件上调用'setBroadcast'方法:

var socket = dgram.createSocket('udp4');

socket.on('listening', function(){
    socket.setBroadcast(true);
});

socket.bind(8000);
Run Code Online (Sandbox Code Playgroud)

  • 这应该是正确的答案,因为绑定是异步的 (3认同)