在 node.js 中分离文件服务器和 socket.io 逻辑

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9709912/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 15:20:14  来源:igfitidea点击:

Separating file server and socket.io logic in node.js

node.jssocket.io

提问by stevendesu

I'm fairly new to node.js and I've found its quite complicated separating a project into multiple files as the project grows in size. I had one large file before which served as both a file server and a Socket.IO server for a multiplayer HTML5 game. I ideally want to separate the file server, socket.IO logic (reading information from the network and writing it to a buffer with a timestamp, then emitting it to all other players), and game logic.

我对 node.js 相当陌生,我发现随着项目规模的增长,将项目分成多个文件非常复杂。我之前有一个大文件,它既用作文件服务器又用作多人 HTML5 游戏的 Socket.IO 服务器。理想情况下,我希望将文件服务器、socket.IO 逻辑(从网络读取信息并将其写入带有时间戳的缓冲区,然后将其发送给所有其他玩家)和游戏逻辑。

Using the first example from socket.io to demonstrate my problem, there are two files normally. app.jsis the server and index.htmlis sent to the client.

使用socket.io的第一个例子来演示我的问题,通常有两个文件。app.js是服务器index.html并发送到客户端。

app.js:

应用程序.js:

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')

app.listen(80);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

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

index.html:

索引.html:

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

To separate file server and game server logic I would need the function "handler" defined in one file, I would need the anonymous function used a callback for io.sockets.on() to be in another file, and I would need yet a third file to successfully include both of these files. For now I have tried the following:

为了分离文件服务器和游戏服务器逻辑,我需要在一个文件中定义的函数“处理程序”,我需要匿名函数使用 io.sockets.on() 的回调在另一个文件中,我还需要一个第三个文件成功包含这两个文件。现在我已经尝试了以下方法:

start.js:

开始.js:

var fileserver = require('./fileserver.js').start()
  , gameserver = require('./gameserver.js').start(fileserver);

fileserver.js:

文件服务器.js:

var app = require('http').createServer(handler),
    fs = require('fs');

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

module.exports = {
    start: function() {
        app.listen(80);
        return app;
    }
}

gameserver:

游戏服务器:

var io = require('socket.io');

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

module.exports = {

    start: function(fileserver) {       
        io.listen(fileserver).on('connection', handler);
    }

}

This seems to work (the static content is properly served and the console clearly shows a handshake with Socket.IO when the client connects) although no data is ever sent. It's as though socket.emit() and socket.on() are never actually called. I even modified handler() in gameserver.jsto add console.log('User connected');however this is never displayed.

这似乎有效(静态内容已正确提供,并且当客户端连接时,控制台清楚地显示与 Socket.IO 的握手),尽管从未发送过任何数据。就好像 socket.emit() 和 socket.on() 从未真正被调用过。我什至修改了 handler()gameserver.js以添加console.log('User connected');但是这从未显示过。

How can I have Socket.IO in one file, a file server in another, and still expect both to operate correctly?

如何在一个文件中使用 Socket.IO,在另一个文件中使用文件服务器,并且仍然期望两者都能正常运行?

回答by Ricardo Tomasi

In socket.io 0.8, you should attach events using io.sockets.on('...'), unless you're using namespaces, you seem to be missing the socketspart:

在 socket.io 0.8 中,您应该使用 附加事件io.sockets.on('...'),除非您使用命名空间,否则您似乎缺少该sockets部分:

io.listen(fileserver).sockets.on('connection', handler)

It's probably better to avoid chaining it that way (you might want to use the ioobject later). The way I'm doing this right now:

最好避免以这种方式链接它(您可能想io稍后使用该对象)。我现在这样做的方式:

// sockets.js
var socketio = require('socket.io')

module.exports.listen = function(app){
    io = socketio.listen(app)

    users = io.of('/users')
    users.on('connection', function(socket){
        socket.on ...
    })

    return io
}

Then after creating the server app:

然后在创建服务器后app

// main.js
var io = require('./lib/sockets').listen(app)

回答by pkyeck

i would do something like this.

我会做这样的事情。

app.js

应用程序.js

var app = require('http').createServer(handler),
    sockets = require('./sockets'),
    fs = require('fs');

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

sockets.startSocketServer(app);
app.listen(80);

and sockets.js

和 sockets.js

var socketio = require('socket.io'),
        io, clients = {};

module.exports = {

        startSocketServer: function (app) {
                io = socketio.listen(app);

                // configure
                io.configure('development', function () {
                        //io.set('transports', ['websocket', 'xhr-polling']);
                        //io.enable('log');
                });

                io.configure('production', function () {
                        io.enable('browser client minification');  // send minified client
                        io.enable('browser client etag');          // apply etag caching logic based on version number
                        io.set('log level', 1);                    // reduce logging
                        io.set('transports', [                     // enable all transports (optional if you want flashsocket)
                            'websocket'
                          , 'flashsocket'
                          , 'htmlfile'
                          , 'xhr-polling'
                          , 'jsonp-polling'
                        ]);
                });
                //

                io.sockets.on('connection', function (socket) {
                        console.log("new connection: " + socket.id);

                        socket.on('disconnect', function () {
                                console.log("device disconnected");

                        });

                        socket.on('connect_device', function (data, fn) {
                                console.log("data from connected device: " + data);
                                for (var col in data) {
                                        console.log(col + " => " + data[col]);
                                }


                        });
                });
        }
};

i just copy&pasted some of my old code - don't really know what changed in the last versions of socket.io, but this is more about the structure than the actual code.

我只是复制并粘贴了我的一些旧代码 - 不知道在 socket.io 的最新版本中发生了什么变化,但这更多的是关于结构而不是实际代码。

and i would only use 2 files for your purposes, not 3. when you think about splitting it up further, maybe one other file for different routes ...

我只会为您的目的使用 2 个文件,而不是 3 个。当您考虑将其进一步拆分时,也许还有一个用于不同路线的文件...

hope this helps.

希望这可以帮助。

回答by Michael Dausmann

I have had a crack at this as well and I am fairly happy with the result. Check out https://github.com/hackify/hackify-serverfor source code.

我也对此有所了解,我对结果相当满意。查看https://github.com/hackify/hackify-server获取源代码。

回答by Marco Godínez

I've another solution. You can use require.js creating a module and pass "app" as an argument. Within the module you can start socket.io and organize your sockets.

我有另一个解决方案。您可以使用 require.js 创建一个模块并将“app”作为参数传递。在模块中,您可以启动 socket.io 并组织您的套接字。

app.js:

应用程序.js

  var requirejs = require('requirejs');

  requirejs.config({
      baseUrl: './',
      nodeRequire: require
  });

  requirejs(['sockets'], function(sockets) {

    var app = require('http').createServer()
      , fs  = require('fs')
      , io  = sockets(app);

      // do something
      // add more sockets here using "io" resource

  });

In your socket.jsmodule you can do something like this:

在您的socket.js模块中,您可以执行以下操作:

  define(['socket.io'], function(socket){
    return function(app){
      var server = app.listen(3000) 
        , io     = socket.listen(server);

      io.sockets.on('connection', function (socket) {
        console.log('connected to socket');

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

        // more more more

      });

      return io;
    }
  });

I hope help you with my contribution.

我希望能帮助你我的贡献。