Node.js,dgram.setBroadcast(标志)由于“EBADF”

我正在使用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) 

一些使用Googlesearch显示 “EBADF”表示“套接字参数不是有效的文件描述符”。 但是我对这个问题不够了解。

首先,你对Stacktrace的格式有一定的理解,所以让我们先澄清一下,然后再看看这里出现的实际错误。

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调用,如果检查失败,则将调用封装到包装的本地UDP套接字setBroadcast方法中。

hello.js上一层,我们用hello.js client.setBroadcast(true);结束第25行的hello.js文件client.setBroadcast(true); 呼叫。

其余的是由hello.js文件的初始加载导致的更多的node.js代码。

实际的错误

node.js在这里包装的本地代码抛出的错误是EBADFUDP一起查找,给了我们:

 EBADF The socket argument is not a valid file descriptor. 

通过进一步深入到node.js的兔子洞,我们最终在udp包装器中 ,它包装了实际C实现的uv包装器,我们在uv包装器中find:

 /* * 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)绑定套接字修复了缺less的初始化,并使程序运行。

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

 var socket = dgram.createSocket('udp4'); socket.on('listening', function(){ socket.setBroadcast(true); }); socket.bind(8000); 

好像文件描述符只是在绑定或发送时创build的,而且在setBroadcast之前是必需的。 在设置广播之前,您可以调用client.bind()带任何参数的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(); });