Node.js dgram绑定在udp6和udp4上抛出EADDRINUSE

时间:2015-09-11 10:36:06

标签: javascript node.js sockets datagram

我最近通过npm安装n将我的node.js版本从0.10.31升级到4.0.0,然后调用n stable

使用新节点版本,我的现有代码破了。

此代码:

var d = require("dgram");
var s = d.createSocket("udp4");
s.bind(9000);
var s6 = d.createSocket("udp6");
s6.bind(9000);

产生以下错误:

events.js:141
  throw er; // Unhandled 'error' event
  ^
Error: bind EADDRINUSE ::0:9000
    at Object.exports._errnoException (util.js:837:11)
    at exports._exceptionWithHostPort (util.js:860:20)
    at dgram.js:213:18
    at doNTCallback3 (node.js:440:9)
    at process._tickCallback (node.js:346:17)
    at Function.Module.runMain (module.js:477:11)
    at startup (node.js:117:18)
    at node.js:951:3

只要IPv6 UDP套接字想要绑定到端口9000。

没有旧节点进程在运行,也没有程序已经在端口9000上侦听。

如果我将第二个绑定命令更改为s6.bind(9001);,则错误不会发生。如果我改变顺序(udp6先绑定,udp4秒),那么当udp4套接字试图绑定时会出现错误。

可能是新节点版本试图使用旧的核心模块或类似的东西吗?

任何人都可以解释这种奇怪的行为吗?

提前感谢您的帮助!

此致

1 个答案:

答案 0 :(得分:4)

在比较旧节点版本0.10.31到4.0.0的源代码之后,我发现了我的代码不再起作用的原因:

因为node.js没有为IPv6 UDP套接字设置标志IPV6_V6ONLY,所以如果启用了SO_REUSEADDR,则一个IPv6套接字和一个IPv4套接字只能侦听同一个端口。旧节点版本(实际上是旧版本的libuv库)隐式设置此选项。新版本允许用户选择,但默认情况下已禁用。

所以我不得不将我的代码更改为以下内容以使其正常工作:

var d = require("dgram");
var s = d.createSocket({type:"udp4",reuseAddr:true});
s.bind(9000);
var s6 = d.createSocket({type:"udp6",reuseAddr:true});
s6.bind(9000);