如何在 NodeJS 中使用 http 模块在同一端口上打开 IPv4 和 IPv6 套接字?
Posted
技术标签:
【中文标题】如何在 NodeJS 中使用 http 模块在同一端口上打开 IPv4 和 IPv6 套接字?【英文标题】:How to open IPv4 and IPv6 sockets on the same port with http module in NodeJS? 【发布时间】:2017-12-30 02:34:42 【问题描述】:我正在运行以下 NodeJS 服务器代码:
var express = require('express');
var path = require('path');
var fs = require('fs');
var bodyParser = require('body-parser');
var http = require('http');
var ejs = require('ejs');
var app = express();
//configure the app
app.set('port', process.env.PORT || 3000);
// set the view engine to ejs
app.set('view engine', 'ejs');
app.use(bodyParser.raw());
app.use(bodyParser.urlencoded(
extended: true
));
app.use(function(req, res, next)
res.set('Access-Control-Allow-Origin', 'https://myServer.com');
res.set('Access-Control-Allow-Methods', 'GET, OPTIONS,POST, PUT, PATCH, DELETE');
res.set('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.set('Access-Control-Allow-Credentials', true);
next();
);
//assets
require(path.join(__dirname, './server.js')).Server(app);
当使用 IPv4 地址参数化服务器时:
var server = http.createServer(app);
//create server
server.listen(app.get('port'), "0.0.0.0", function()
var host = server.address().address;
console.log('mockserver listening on host:' + host + ":" + app.get('port'));
);
Netstat 给出以下输出:
# netstat -plnt | grep node
tcp 0 0 0.0.0.0:3000 0.0.0.0:* LISTEN 1234/node /local/op
在这种情况下,TCP 套接字是使用 IPv4 地址创建的。只能使用 IPv4 地址访问该服务。
当使用 IPv6 地址参数化服务器时:
var server = http.createServer(app);
//create server
server.listen(app.get('port'), "::", function()
var host = server.address().address;
console.log('mockserver listening on host:' + host + ":" + app.get('port'));
);
netstat 给出以下输出:
# netstat -plnt | grep node
tcp6 0 0 :::3000 :::* LISTEN 1234/node /local/op
可以同时使用 IPv4 和 IPv6 地址访问该服务。 (可能是打开了模拟 IPv4 的内核选项)
问题: 是否可以使用 NodeJS 的 express 模块为给定端口创建单独的(IPv4 和 IPv6)套接字?
我想要一个 netstat 的输出与此类似的解决方案:
# netstat -plnt | grep node
tcp 0 0 0.0.0.0:3000 0.0.0.0:* LISTEN 1234/node /local/op
tcp6 0 0 :::3000 :::* LISTEN 1234/node /local/op
尝试:我尝试了以下尝试,但均无效:
第一次尝试:我尝试用一台服务器打开多个套接字,但监听函数的参数化可能与我想象的不同。
server.listen(app.get('port'), ["0.0.0.0", "::0"], function()
console.log('EEA-mockserver server listening on host:' + app.get('port'));
);
或
server.listen(app.get('port'), "0.0.0.0", "::0", function()
console.log('EEA-mockserver server listening on host:' + app.get('port'));
);
第二次尝试:我尝试在同一个端口上创建多个服务器,但是当他们想通过同一个端口初始化自己时会发生冲突。
var server4 = http.createServer(app);
var server6 = http.createServer(app);
server4.listen(app.get('port'), "0.0.0.0", function()
var host = server4.address().address;
console.log('EEA-mockserver server listening on host:' + host + ":" + app.get('port'));
);
server6.listen(app.get('port'), "::", function()
var host = server6.address().address;
console.log('EEA-mockserver server listening on host:' + host + ":" + app.get('port'));
);
【问题讨论】:
对我来说,解决方案是指定 IPv6(例如:::1
)而不是 ::
,它确实有效。缺点是它不会监听所有的 IPv6,需要指定它们。
【参考方案1】:
称为双栈模式,与平台配置有关。 Linux 操作系统允许您通过 net.ipv6.bindv6only sysctl 打开/关闭它。我猜 Windows 也有类似的东西。
【讨论】:
以上是关于如何在 NodeJS 中使用 http 模块在同一端口上打开 IPv4 和 IPv6 套接字?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 nodejs 模块 http2 将 http2 与 ExpressJS 集成?
phantomjs:如何在phantomjs中使用npm模块?