2012-03-14 39 views
60

我對node.js相當陌生,隨着項目規模的擴大,我發現將項目分割成多個文件相當複雜。我之前有一個大文件作爲多人遊戲HTML5遊戲的文件服務器和Socket.IO服務器。我最好想分開文件服務器,socket.IO邏輯(從網絡讀取信息並將其寫入具有時間戳的緩衝區,然後發送給所有其他玩家)以及遊戲邏輯。分離node.js中的文件服務器和socket.io邏輯

使用socket.io中的第一個例子來演示我的問題,通常有兩個文件。 app.js是服務器,index.html發送給客戶端。

app.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:

<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> 

爲獨立的文件服務器,我需要在一個文件中定義的函數 「處理程序」 的遊戲服務器邏輯,我需要匿名函數使用io.sockets.on()的回調函數放入另一個文件中,並且我還需要第三個文件才能成功地包含這兩個文件。現在我已經試過如下:

start.js:

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

fileserver.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; 
    } 
} 

遊戲服務器:

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); 
    } 

} 

這似乎是工作(靜態內容得到適當的處理,並且控制檯在客戶端連接時清楚地顯示與Socket.IO握手),儘管沒有數據曾發送過。就好像socket.emit()和socket.on()從來沒有被實際調用過。我甚至在gameserver.js中修改了處理函數()來添加console.log('User connected');但是,這是從不顯示的。

如何在一個文件中使用Socket.IO,在另一個文件服務器中使用Socket.IO,並且仍然希望兩者都能正常運行?

+4

你知道express js框架嗎? http://expressjs.com/這很棒,真的可以幫助你構建你的應用程序。在github上有很多例子(https://github.com/visionmedia/express/tree/master/examples)也許有些東西可以幫助你解決你的問題... – pkyeck 2012-03-18 23:00:46

+1

@pkyeck:我正在閱讀expressjs現在試圖弄清楚它是如何使我受益的,但到目前爲止,它似乎比我所需要的更復雜。我真正想要的是將遊戲服務器和文件服務器的邏輯分成兩個單獨的文件,然後有第三個文件正確啓動兩臺服務器。 – stevendesu 2012-03-19 15:36:52

+0

你有沒有時間查看我的「新」答案? – pkyeck 2012-03-21 09:55:57

回答

74

In socket.io 0。8,你應該使用io.sockets.on('...')事件,除非你使用的命名空間連接,你似乎缺少sockets部分:

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

它可能會更好,以避免鏈接這種方式(你可能想使用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 
} 

然後創建服務器app後:

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

很好的答案,試圖將其移植到krakenJS,但socket.io模塊永遠不會啓動:/ – Ms01 2014-03-01 20:25:04

+1

我們不正確地使用'return io'嗎?它僅適用於var io。 – Sobiaholic 2014-11-30 07:32:37

+0

如果我想觸發發射請求?例如'app.get('/ some/url',function(req,res){//我想在這裏發出})' – 2017-12-25 10:29:37

5

我會做這樣的事情。

app.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); 

和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]); 
           } 


         }); 
       }); 
     } 
}; 

我只是複製粘貼&我的一些舊的代碼 - 真的不知道插座的最後一個版本是什麼改變了。 io,但是這比實際的代碼更關於結構。

,當你想進一步分割它,也許有其他的文件不同的路線......

希望這可以幫助我只會用兩個文件你的目的,而不是3 。

+0

現在它只是一個文件服務器和一個socket.io服務器,但是最終我還會有遊戲邏輯來確定運動更新中的玩家位置,並且我需要具有滯後最小化邏輯,該邏輯會查看每個客戶端的ping並估計哪些他們目前正在從現有數據判斷的遊戲狀態。有一些邏輯來快速轉發時間,一些倒回時間的邏輯,一些移動播放器的邏輯,一些處理網絡數據的邏輯以及一些處理文件的邏輯意味着我想將所有東西都分成不同的文件,理想情況是。不只是socket.io的東西。 – stevendesu 2012-03-21 13:23:26

+0

這只是開始 - 您發佈的文件。你可以做多個'var xxx = require('./ xxx');'並將你的應用分成多個文件。我昨天在mongodb conf,10gen的一個人展示了一個基於node/mongo/websockets(https://github.com/christkv/mongoman)的遊戲,他通過套接字發送BSON數據並解碼客戶端上的數據 - 使爲了加快客戶端/服務器之間的通信......也許這對你很有趣! – pkyeck 2012-03-21 14:14:04

0

我有另一種解決方案。您可以使用require.js創建一個模塊並將「app」作爲參數。在模塊內,您可以啓動socket.io並組織您的套接字。

app.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 

    }); 

在你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; 
    } 
    }); 

我希望幫助你我的貢獻。

+1

如果有人讀到這個問題,不,根本沒有理由在節點內使用AMD。 – 2013-11-12 19:22:00

+0

這只是一種選擇,不是唯一的方法 – 2014-01-09 17:52:53