【问题标题】:node.js + socket.io + express.js: No connectionnode.js + socket.io + express.js:没有连接
【发布时间】:2014-01-03 12:30:28
【问题描述】:

我一直在尝试设置一个简单的 socket.io 示例,但它拒绝正常工作。客户端在 Apache2 上运行,应该通过 3000 端口访问 node.js-server。

似乎没有 任何 连接,并且服务器是否实际运行似乎并不重要 - 如果在服务器上手动停止 node.js 进程($ kill xyz ),我的客户端控制台不会引发任何错误。应用运行时会出现完全相同的结果 (info - socket.io started)。

服务器

// Check dependencies & setup backend
var express = require('express');
var server = express();
var http = require('http');
var app = http.createServer(server); // somehow needed? ("Socket.IO's `listen()` method expects an `http.Server` instance as its first parameter.")
var socket = require('socket.io');
// listen @ port 3000 as definied by proxy
server.listen(3000);
// listen w/ socket.io as well
var io = socket.listen(app);

...

// socket.io
// TODO: test, added 01/03/14 
io.set('match origin protocol', true);
io.set('log level', 2);
var clients = io.sockets.clients();
io.sockets.on('connection', function(client) {
    console.log('Connection from ' + client);

    client.emit('news', {
        hello : 'world'
    });

    client.on('event', function(data) {
        console.log(data);
    });
});

客户

<script type="text/javascript" src="./js/socket.io.js" ></script>
        <script>
            try {
                var socket = io.connect('https://localhost:3000');
                console.log(io);
                console.log('check 1', socket.socket.connected); // false

                socket.on('connect', function() {
                    console.log('check 2', socket.socket.connected); // not reached
                });

                socket.on('news', function(data) {
                    console.log(data);
                });

            } catch(error) {
                console.log(error);
            } finally {
                console.log('fin');
            }
        </script>

编辑 2:

此代码有效,但仅在本地。我什至在服务器上安装了 Apache 2.4 以确保我可以访问 WebSockets(我在某处读到它们在 2.2.x 中不可用)。 服务器:

var express = require('express');
var app = express();
var server = app.listen(3000);
var io = require('socket.io').listen(server);

app.use(express.static(__dirname + '/'));

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

客户:

<script type="text/javascript" src="js/socket.io.js" ></script> 
        <script>
            var socket = io.connect('ws://localhost:3000');
            socket.on('news', function(data) {
                console.log(data);
                socket.emit('my other event', {
                    my : 'data'
                });
            });

        </script>

【问题讨论】:

  • 您的服务器端代码应该使用app.listen(而不是server.listen)。您的客户端应该使用:src="/socket.io/socket.io.js"。如果您还想为 Apache 启用 websocket,请查找有关它的文档
  • 我不能简单地使用socket.io/socket.io.js,因为客户端存储在/var/www/xyz,而node.js 位于/var/node。所以我只是将它复制到正确的位置:$ ./node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js $ cp ./node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js /var/www/xyz/js。 Websockets 似乎在 Apache 2.2 中不可用,建议的解决方案似乎只使用 xhr-polling。不幸的是,这也不起作用。

标签: javascript node.js apache express socket.io


【解决方案1】:

好的,伙计们,我终于启动并运行它了。

我所做的是将反向代理从 Apache 迁移到 node.js/node-http-proxy-solution。我不确定这是否真的是强制性的——但是在重新配置 Apache 2.2.2 甚至编译 Apache 2.4.7 都没有帮助之后,我认为这值得一试。我还切换到子域而不是子目录,因为子目录在某些情况下似乎也会引起问题。同样,不知道这只是预防措施还是真的有必要。

然而,我很确定相关的是如何加载 socket.io.js。由于我的反向代理已经将请求转发到正确的(内部)IP,我必须通过不带端口或 ws:// 的 TLD 访问 socket.io.js 以及实际的 Websocket。

长话短说,以下是相关代码:

服务器

var express = require('express');
var app = express();
var server = app.listen(3000);
var io = require('socket.io').listen(server);

app.use(express.static(__dirname + '/'));

console.log('Express server started on port %s', app);

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

客户

<script src="http://mysubdomain.mydomain.com/socket.io/socket.io.js"></script>
<script>
    var socket = io.connect('http://mysubdomain.mydomain.com');
    // , {secure: true}

    socket.on('news', function(data) {
        console.log(data);
    });
</script>

代理

var fs = require('fs'), httpProxy = require('http-proxy');

// This will crash as soon as Apache isn't running or the port isn't binded elsewhere
// TODO: fix
var proxyTable = {
    'mydomain.com/subdir' : '127.0.0.1:3000',
    'mysubdomain.mydomain.com' : '127.0.0.1:3000'
};

var httpOptions = {
    hostnameOnly : false,
    router : proxyTable
};

var httpsOptions = {
    hostnameOnly : false,
    router : proxyTable,
    https : {
        key : fs.readFileSync('/path/key', 'utf8'),
        cert : fs.readFileSync('/path/cert', 'utf8')
    }
};

httpProxy.createServer(httpOptions).listen(80); 
httpProxy.createServer(httpsOptions).listen(443);

最后但并非最不重要的一点是,对于通过 google 偶然发现此问题的任何人,使用的版本:

$ npm list --depth=0
myapp@0.0.0 /path/app
├── express@3.4.7
└── socket.io@0.9.16

$ npm list --depth=0
/path/proxy
└── http-proxy@0.10.4

【讨论】:

  • 使用 nginx 代理是轻松且直接的 - 最新版本默认支持 WebSockets 流量进行代理,因此它与 node.js 一起工作得更好、更高效。事实上,您的 socket.io 连接可能只使用 XHR-Long-Polling,而不是 WebSockets,因为 Apache 可能不知道如何处理 WS 流量。仔细检查这一点,因为在这种情况下,您会损失很多网络性能。
  • 感谢您发布此内容,我遇到了同样的错误,您的示例帮助了我!
【解决方案2】:

请按照此处的示例进行操作:http://socket.io/#how-to-use

var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var socket = require('socket.io');
var io = socket.listen(server);
app.listen(3000);

另外这是错误的:

io.connect('https://localhost:3000');

应该是ws://localhost:3000/

【讨论】:

  • 抛开变量名:这似乎与我的设置几乎相同并产生相同的错误。
  • 添加了更多。伙计,老实说,你做错了太多事情。所以,请从socket.io/#how-to-use 上的简单示例开始,并不断改进它。但从简单开始。
  • 如果调用app.listen(),app会创建一个内部http服务器,所以serverio对象是没有意义的(?)
  • app - 指向express。表达它自己取决于http。如果您调用http.createServer,它会将http 套接字附加到app(快速),以便下一次调用socket.listen 将绑定到同一个http 服务器。当你打电话给app.listen - 那家伙将使用我们之前创建的http服务器。所以他们都有关系。请检查我在答案中提供的链接中的默认示例,并与他们一起玩以进一步了解它。
  • 这些例子都不起作用。 express.js + socket.io 的给定示例指的是 Express 2.0,github 上的“新”文档适用于未发布的 1.0 版本。在我的 Mac 上使用npm install socket.io express 设置一个新的本地项目,使用您的代码初始化服务器(因为官方示例不起作用)及其 index.html 示例,我得到的只是"NetworkError: 404 Not Found - http://127.0.0.1:8020/socket.io/socket.io.js"。此外,没有提到使用 ws://-protocol。我现在真的很困惑。
猜你喜欢
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-27
  • 2018-05-14
  • 2015-04-01
  • 2012-08-20
  • 2018-01-09
相关资源
最近更新 更多