0

現在、node.js サーバーと通信する単純な Flash ゲームを開発しようとしています。

私の質問は次のとおりです: Web リクエストとゲーム リクエストを区別するサーバーを作成するにはどうすればよいですか?

ここに私がやったことの詳細があります:

以前は、netstaticモジュールを使用して、ゲーム クライアントとブラウザーからのリクエストをそれぞれ処理していました。

TwoServers.js

// Web server
var file = new staticModule.Server('./public');
http.createServer(function(req, res){
    req.addListener('end', function(){
        file.serve(req, res, function(err, result){
                     // do something
        });
    });
}).listen(port1, "127.0.0.1");

// Game Server
var server = net.createServer(function(socket)
{
    // handle messages to/from Flash client
    socket.setEncoding('utf8');
    socket.write('foo');
    socket.on('data', onMessageReceived);
});
server.listen(port2, "127.0.0.1");

1 つのポートでリッスンするExpressサーバーだけで上記のことを行いたいのですが、どうすればよいかわかりません。

これが私が考えていることです(実際には機能しません)。

OneServer.js

var app = express();
app.configure(function()
{
    // ...
    app.use('/',express.static(path.join(__dirname, 'public')));  // The static server
});

app.get('/', function(req, res)    // This is incorrect (expects http requests)
{
    // Handle messages to/from Flash client
    var socket = req.connection;
    socket.setEncoding('utf8');
    socket.write('foo');
    socket.on('data', onMessageReceived);
});
app.listen(app.get('port'));   // Listen in on a single port

しかし、Web ページのリクエストとゲームからのリクエストを区別できるようにしたいと考えています。

: Actionscript のXMLSocketは TCP リクエストを行うため、app.get('/') の使用は次の 2 つの理由から正しくありません。

  1. Flash がソケットに書き込むとき、http プロトコルを使用していないため、ゲームが接続を試みても app.get('/') は起動されません。

  2. net.Socketオブジェクトを修正するためのアクセス権がないため、正しいソケットとの間で読み書きを行うことは期待できません。代わりに、Web ページの要求に関連付けられたソケットに対して読み取り/書き込みを行います。

これについての助けをいただければ幸いです(特に、これについて間違った方法で推論している場合)。

4

1 に答える 1

2

特定のポートに対して TCP 接続が開かれると、サーバー (Node + Express) は、誰がその接続を行ったか (それがブラウザーなのかカスタム クライアントなのか) を知る方法がありません。

したがって、ポート 80 にある Express サーバーと通信する場合、カスタム クライアントは HTTP を使用する必要があります。そうしないと、(カスタム プロトコルで) 新しく開いたソケットを介して送信するデータは、Express にとってゴミのように見えます接続を閉じます。

ただし、これは、カスタム プロトコルを話す TCP ストリームを取得できないという意味ではありません。最初に HTTP を話して、プロトコルの切り替えを要求するだけです。HTTP はまさにこれを実現するためのメカニズム (Upgradeヘッダー) を提供します。実際、これが WebSocket の実装方法です。

Flash クライアントが最初にサーバーへの TCP 接続を開くとき、送信する必要があります: (改行はCRLF文字として送信する必要があることに注意してください。別名\r\n)

GET /gamesocket HTTP/1.1
Upgrade: x-my-custom-protocol/1.0
Host: example.com
Cache-Control: no-cache
​

の値Upgradeは任意であり、Hostすべての HTTP リクエストに対して送信する必要があり、Cache-Controlヘッダーにより、中間プロキシがこのリクエストにサービスを提供しないことが保証されます。要求が完了したことを示す空白行に注意してください。

サーバーは次のように応答します。

HTTP/1.1 101 Switching Protocols
Upgrade: x-my-custom-protocol/1.0
Connection: Upgrade
​

繰り返しますが、空行はヘッダーが完全であることを示し、その finalCRLFの後、任意のデータを任意の形式で TCP 接続を介して自由に送信できるようになります。

これのサーバー側を実装するには:

app.get('/gamesocket', function(req, res) {
    if (req.get('Upgrade') == 'x-my-custom-protocol/1.0') {
         res.writeHead(101, { Upgrade: req.get('Upgrade'), Connection: 'Upgrade' });

         // `req.connection` is the raw net.Socket object
         req.connection.removeAllListeners(); // make sure Express doesn't listen to the data anymore... we've got it from here!

         // now you can do whatever with the socket
         req.connection.setEncoding('utf8');             
         req.connection.write('foo');
         req.connection.on('data', onMessageReceived);
    } else res.send(400); // bad request
});

もちろん、TCP はメッセージベースのプロトコルではなく、ストリームのみを提供することを覚えおいてください。したがって、 のdataイベントはSocket、単一の論理メッセージを複数のイベントにフラグメント化するか、単一のイベントに複数の論理メッセージを含めることさえできます。手動でデータをバッファリングする準備をしてください。

ここでの他のオプションは、WebSockets サーバーと WebSockets プロトコルの上に独自のプロトコルを実装するsocket.ioを使用することです。WebSockets プロトコルメッセージベースです。ほとんどの場合、ここで概説したように機能し、HTTP ネゴシエーションの後、TCP 接続の上にメッセージ フレーミング レイヤーを追加して、アプリケーションがデータ ストリームを心配する必要がないようにします。(WebSocket を使用すると、必要に応じて HTML ページからサーバーに接続する可能性も開かれます。)

利用可能なFlash socket.io クライアントがあります。

于 2013-01-23T05:21:14.723 に答える