Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 对socket.io同时使用http和https_Node.js_Ssl_Express_Socket.io - Fatal编程技术网

Node.js 对socket.io同时使用http和https

Node.js 对socket.io同时使用http和https,node.js,ssl,express,socket.io,Node.js,Ssl,Express,Socket.io,我试图使socket.io在http和https连接上都能工作,但在我的配置中,它似乎只能在其中一个连接上工作 使用下面的配置选项,socket.io可以通过https访问我的应用程序,但当尝试通过常规http访问时,它无法连接,并且我收到错误 var app = express() , http= require('http').createServer(app) , https = require('https').createServer(options, app) ,

我试图使socket.io在
http
https
连接上都能工作,但在我的配置中,它似乎只能在其中一个连接上工作

使用下面的配置选项,socket.io可以通过https访问我的应用程序,但当尝试通过常规http访问时,它无法连接,并且我收到错误

    var app = express()
  , http= require('http').createServer(app)
  , https = require('https').createServer(options, app)
  , io = require('socket.io').listen(https, { log: false })
后来我有了这个

http.listen(80, serverAddress);
https.listen(443, serverAddress);
在客户端,我有以下内容:

<script src='/socket.io/socket.io.js'></script>

var socket = io.connect('https://<%= serverAddress %>', {secure: true, 'sync disconnect on unload' : true});
正因为如此,我还得到了其他一些,如:

Uncaught ReferenceError: io is not defined 

我做过类似的事情,它需要两个socket.io实例。大概是这样的:

var express = require('express');
var oneServer = express.createServer();
var anotherServer = express.createServer();
var io = require('socket.io');

var oneIo = io.listen(oneServer);
var anotherIo = io.listen(anotherServer);
当然,您需要注入两次消息:对于两个socket.io实例


一个好的选择是将SSL处理委托给您的代码,并在代码中忘记SSL。

我猜跨源请求可能是您出错的原因。协议中的更改被视为域中的更改。因此,对于通过
http
服务器提供的页面,访问
https
服务器(连接到它的websocket服务器)可能会引发安全错误。请参见有关如何在express中启用CORS的示例

您还应该将标题中的
*
更改为
http://serverAddress , https://serverAddress
。允许所有站点不是一个好主意,使用它进行测试


如果您试图在
http
https
服务器之间使用AJAX,情况也是如此。请发布错误,只是为了确定它。

我使用不同的方法解决了问题,我将服务器配置为仅支持未加密传输,并用于https支持

有关如何安装
stunnel
的信息,请检查此项

然后,使用以下con配置:

#/etc/stunnel/stunnel.conf
cert = /var/www/node/ssl/encryption.pem
[node]
accept = 443
connect = 80
最后,我使用以下方法连接客户端:

var socket = that.socket = io.connect('//'+server);

这将相应地使用http/https进行连接。

可以说,http和https的node.js服务器对象应该能够侦听任意数量的端口和接口,无论是否使用SSL,但目前似乎尚未实现。(我能够让一台服务器在两个端口上侦听,方法是将没有请求侦听器的第二台服务器作为“句柄”参数传递给server.listen(句柄,[callback])接口,以及server.listen(端口,[hostname],[backlog],[callback]),但它不能与SSL/非SSL服务器混合使用。)

前面提到的stunnel解决方案当然是一个可行的选择,但如果不希望安装单独的软件(以避免非node.js依赖关系),则可以在node.js中以本机方式实现相同的隧道(假设端口80上有HTTP,端口443上有HTTPS):


这将具有与使用特技相同的效果。换句话说,它将避免需要两个单独的socket.io服务器实例,同时也使node.js“https”模块冗余。

我认为问题在于您在服务器端和客户端设置socket.io的方式

以下是我如何让它工作的(只为你)

服务器:

var debug = require('debug')('httpssetuid');
var app = require('../app');
var http = require('http');
var https = require('https');
var fs = require('fs');
var exec = require('child_process').exec;
var EventEmitter = require('events').EventEmitter;
var ioServer = require('socket.io');

var startupItems = [];
startupItems.httpServerReady = false;
startupItems.httpsServerReady = false;

var ee = new EventEmitter();

ee.on('ready', function(arg) {
  startupItems[arg] = true;
  if (startupItems.httpServerReady && startupItems.httpsServerReady) {
    var id = exec('id -u ' + process.env.SUDO_UID, function(error, stdout, stderr) {
      if(error || stderr) throw new Error(error || stderr);
      var uid = parseInt(stdout);
      process.setuid(uid);
      console.log('de-escalated privileges. now running as %d', uid);
      setInterval(function cb(){
        var rnd = Math.random();
        console.log('emitting update: %d', rnd);
        io.emit('update', rnd);
      }, 5000);
    });
  };
});

app.set('http_port', process.env.PORT || 80);
app.set('https_port', process.env.HTTPS_PORT || 443);

var httpServer = http.createServer(app);

var opts = {
  pfx: fs.readFileSync('httpssetuid.pfx')
};
var httpsServer = https.createServer(opts, app);

var io = new ioServer();

httpServer.listen(app.get('http_port'), function(){
  console.log('httpServer listening on port %d', app.get('http_port'));
  ee.emit('ready', 'httpServerReady');
});

httpsServer.listen(app.get('https_port'), function(){
  console.log('httpsServer listening on port %d', app.get('https_port'));
  ee.emit('ready', 'httpsServerReady');
});

io.attach(httpServer);
io.attach(httpsServer);

io.on('connection', function(socket){
  console.log('socket connected: %s', socket.id);
});
script(src='/socket.io/socket.io.js')
script.
  var socket = io();
  socket.on('update', function(update){
    document.getElementById('update').innerHTML = update;
  });
客户端:

var debug = require('debug')('httpssetuid');
var app = require('../app');
var http = require('http');
var https = require('https');
var fs = require('fs');
var exec = require('child_process').exec;
var EventEmitter = require('events').EventEmitter;
var ioServer = require('socket.io');

var startupItems = [];
startupItems.httpServerReady = false;
startupItems.httpsServerReady = false;

var ee = new EventEmitter();

ee.on('ready', function(arg) {
  startupItems[arg] = true;
  if (startupItems.httpServerReady && startupItems.httpsServerReady) {
    var id = exec('id -u ' + process.env.SUDO_UID, function(error, stdout, stderr) {
      if(error || stderr) throw new Error(error || stderr);
      var uid = parseInt(stdout);
      process.setuid(uid);
      console.log('de-escalated privileges. now running as %d', uid);
      setInterval(function cb(){
        var rnd = Math.random();
        console.log('emitting update: %d', rnd);
        io.emit('update', rnd);
      }, 5000);
    });
  };
});

app.set('http_port', process.env.PORT || 80);
app.set('https_port', process.env.HTTPS_PORT || 443);

var httpServer = http.createServer(app);

var opts = {
  pfx: fs.readFileSync('httpssetuid.pfx')
};
var httpsServer = https.createServer(opts, app);

var io = new ioServer();

httpServer.listen(app.get('http_port'), function(){
  console.log('httpServer listening on port %d', app.get('http_port'));
  ee.emit('ready', 'httpServerReady');
});

httpsServer.listen(app.get('https_port'), function(){
  console.log('httpsServer listening on port %d', app.get('https_port'));
  ee.emit('ready', 'httpsServerReady');
});

io.attach(httpServer);
io.attach(httpsServer);

io.on('connection', function(socket){
  console.log('socket connected: %s', socket.id);
});
script(src='/socket.io/socket.io.js')
script.
  var socket = io();
  socket.on('update', function(update){
    document.getElementById('update').innerHTML = update;
  });
以下是服务器的关键点:

  • 需要socket.io,但不要调用它的listen方法(假设已经需要http和https)。相反,只需保留引用即可。(var ioServer=require('socket.io'))
  • 创建您的http&https服务器
  • 创建ioServer的新实例
  • 绑定http和https服务器(.listen)
  • 将http&https服务器实例附加到io实例。(.listen是.attach的别名)
  • 设置io事件
  • 客户机(但你知道了):

  • include socket.io脚本标记
  • 调用io和捕获引用
  • 设置事件处理程序

  • 在客户端上,不需要调用io.connect()。此外,我不确定你在那里的选择。看起来您有一个输入错误(,),我在1.0文档中找不到任何关于安全的参考:true。

    来自
    http
    的客户端是否能够与连接到
    https
    的人通信?关于
    stunnel
    我已经试过了,也试过了
    httpproxy
    ,但是我不能让它们正常工作。你能举个例子吗?抱歉耽搁了。是的,stunnel负责SSL并透明地解密连接到https端口(443)的客户端,使它们看起来像是连接到express http端口(80)。以下是stunnel的一个简单配置要点,该配置监听443并将所有传入流量转发到同一主机的端口80:谢谢,我添加了收到的错误。我尝试启用CORS,然后我了解到,我在客户端
    头部
    包含socket.io的方式应该改变,因为请求始终是针对htpps的,而不是相对于url的。但是它没有很好地工作,我遇到了一些其他错误,比如
    NETWORK\u ERR:XMLHttpRequest Exception 101
    ,这一定是因为我使用的是WebSocket,如果不可用,则是XHR轮询。这个错误是在您添加的问题错误之后出现的吗,或者您添加的错误已被此错误替换。现在发生的错误是由于同源策略造成的。你能说出引起这个错误的线路吗。可能CORS请求失败是因为某些url。我使用了此方法,但它在我的系统中不起作用,对于http,所有东西都能正常工作,但我不知道如何配置https,我使用了节点、套接字io、redis和rails,所以我始终需要连接端口9876
    http.listen(9876,function(){console.log('listening on*:9876');}),我在stunnel.conf中添加了您的代码。但不起作用。你能帮助我吗?