4

我一直在这个问题上花费数小时,但无济于事。

编辑:找到解决方案(见我的回答)

项目背景

我正在构建一个项目Symfony2,它需要一个用于上传大文件的模块。我选择了Node.jsand Socket.IO(我必须从头开始学习,所以我可能会遗漏一些基本的东西)。我将这些与 HTML5 File 和 FileReader API 结合起来,将文件以切片的形式从客户端发送到服务器。初步测试表明,这种方法作为一个独立的应用程序非常有效,其中所有内容都由 处理和服务Node.js,但与集成ApacheSymfony2似乎存在问题。

该应用程序有一个不安全和安全的部分。我的目标是Apache在端口上使用80443为内置的大部分应用程序提供服务Symfony2,并Node.jsSocket.io端口上8080用于文件上传。连接到套接字的客户端页面将由 提供Apache,但套接字将通过 运行Node.js。上传模块必须通过 HTTPS 运行,因为页面驻留在具有经过身份验证的用户的安全环境中。

问题是事件使用socket.emitsocket.send似乎不起作用。客户端到服务器,或服务器到客户端,没有区别。没有任何反应,也没有错误。

编码

显示的代码是我的代码的简化版本,没有混乱和敏感数据。

服务器

var httpsModule = require('https'),
    fs = require('fs'),
    io = require('socket.io');

var httpsOptions = 
{
    key: fs.readFileSync('path/to/key'),
    cert: fs.readFileSync('/path/to/cert'),
    passphrase: "1234lol"
}

var httpsServer = httpsModule.createServer(httpsOptions);
var ioServer = io.listen(httpsServer);

httpsServer.listen(8080);

ioServer.sockets.on('connection', function(socket)
{
    // This event gets bound, but never fires
    socket.on('NewFile', function(data)
    {
        // To make sure something is happening
        console.log(data);

        // Process the new file...
    });

    // Oddly, this one does fire
    socket.on('disconnect', function()
    {
        console.log("Disconnected");
    });
});

客户

// This is a Twig template, so I'll give an excerpt
{% block javascripts %}
{{ parent() }}

<script type="text/javascript" src="https://my.server:8080/socket.io/socket.io.js"></script>
<script type="text/javascript">

    var socket = io.connect("my.server:8080",
                {
                    secure: true,
                    port: 8080
                });


    // Imagine this is the function initiating the file upload
    // File is an object containing metadata about the file like, filename, size, etc.
    function uploadNewFile(file)
    {
         socket.emit("NewFile", item);
    }

</script>
{% endblock %}

所以问题是...

当然,该应用程序还有更多内容,但这就是我被困的地方。页面加载完美,没有错误,但发出事件永远不会触发或到达服务器(断开连接事件除外)。我已经尝试在客户端和服务器上使用消息事件来检查它是否只是自定义事件的问题,但这也不起作用。我猜有些东西阻止了客户端-服务器通信(它不是防火墙,我已经检查过了)。

我在这里完全不知所措,所以请帮忙。

编辑:找到解决方案(见我的回答)

4

1 回答 1

3

经过一番艰苦的调试,我发现我的设置出了什么问题。不妨分享一下我的发现,尽管它们(我认为)与 Node.js、Socket.IO 或 Apache 无关。

正如我所提到的,我的问题简化了代码,以向您展示我的设置而不会造成混乱。然而,我是通过一个对象设置客户端,使用属性来配置套接字连接。像这样:

var MyProject = {};

MyProject.Uploader =
{
    location: 'my.server:8080',
    socket: io.connect(location,
            {
                secure: true,
                port: 8080,
                query: "token=blabla"
            }),
    // ...lots of extra properties and methods
}

问题在于location用作属性名称。它是 Javascript 中的保留字,在这种情况下会产生一些奇怪的行为。我发现一个对象的属性名不能是保留字很奇怪,所以我决定测试一下。我还注意到我错误地引用了该属性,我忘记this.location在连接到套接字时使用。所以我把它改成了这个,只是作为一个测试。

var MyProject = {};

MyProject.Uploader =
{
    location: 'my.server:8080',
    socket: io.connect(this.location,
            {
                secure: true,
                port: 8080,
                query: "token=blabla"
            }),
    // ...lots of extra properties and methods
}

但无济于事。我仍然没有通过套接字获取数据。因此,在我沮丧驱动的调试狂潮中,下一步似乎是合乎逻辑的。更改属性名称修复了一切!

var MyProject = {};

MyProject.Uploader =
{
    socketLocation: 'my.server:8080',
    socket: io.connect(this.socketLocation,
            {
                secure: true,
                port: 8080,
                query: "token=blabla"
            }),
    // ...lots of extra properties and methods
}

这种方法效果很好,我收到了大量的调试消息。成功!!如果您碰巧使用了保留字,我不知道是否是 Javascript 中的预期行为会覆盖(或者这里发生的任何事情,“滥用”感觉像是现在把它交给我的更好方式)对象属性。我只知道从现在开始我要避开他们!

希望它可以帮助那里的任何人!

于 2013-05-16T11:07:38.180 回答