2011-05-18 8 views
9

TCPを使用したNet Stream Objectは(node.js introduction videoのプリセットエンドとして)うまく機能しますが、HTTPでこれをどのように行う必要がありますか?Node.JS:HTTPチャットサーバーの作成方法

http.createServer()内のソケット/クライアントにアクセスする方法はありますか?またはそれを行う方法は何ですか?私は公式node chat demossouce codeから解決策を見つけようとしましたが、私は本当に理解していません。

私はクライアントサイドjsを理解していますが、私は(クライアントとして)トラフAJAXをサーバーサイドjsに送信した後に何が起こっていますか?サーバー上の他のクライアントにもどうすれば送信できますか?

私はプロセスのロジックを覚えていないので、socket.ioやその他のフレームワーク、ライブラリ、モジュールを使用したくないことに注意してください。

ありがとうございました!

答えて

2

これを実行する1つの方法は、メッセージの配信者として機能するチャネルにクライアントを「購読する」ことです。一度加入すると、クライアントはチャネルに送信された各メッセージのコピーを受信します。

多くのノードチャットサービスは、1つから任意の数のクライアントへのこのメッセージの配信を処理するためにredisのpubsub機能に依存しています。あなたが「あなた自身のロールを作りたい」なら、この問題を赤字がどのように解決するかを理解することは、素晴らしいスタートとなるでしょう。

+1

しかし、メッセージはクライアントにどのように送信されるのですか?これは興味深いですが、これは面白いですが、node.jsには関係ありません:)しかし、PHPプログラマとしては面白そうです – Adam

+0

クライアントはサービスに加入すると、キューが作成されます他のクライアントから送信されたメッセージクライアントがメッセージを送信すると、それは他の各サブスクライバのキューに追加されます。次に、クライアントは、独自のキューに追加された保留中のメッセージを要求します。 –

+2

WebSocket(HTML5の機能)を使用すると、クライアントは、サーバーがクライアントにメッセージを「プッシュ」するために使用できるWebサーバーへの双方向ソケットを開くことができます。この機能がない場合、クライアントはAJAXを介してサーバーにポーリングメッセージをポーリングします。サーバーはmsgsをプッシュしません(WebSocketが存在しないため)、ネイティブ機能はありません。これがsocket.ioがとても有用な理由です。クライアントがWebソケットをサポートしている場合、クライアントはそれらを使用します。そうでなければ、それは長いポーリングに落ちる他の多くの手段を試みる。 –

10

理想的にはWebSocketsを使用しますが、代替方法はajax long pollingです。

ロングポーリングと呼ばれる手法を使用してチャットを行うことができます。これは、サーバーに(ajax)リクエストを行い、送信するデータが残るまでサーバーはこの要求を保持し続けることを意味します。

クライアントが定期的にサーバーをポーリングするので、サーバーに新しいメッセージがない場合は、ユーザーの要求が保持されます。メッセージがあれば、それをクライアントに送り返し、クライアントはサーバーを再びポーリングします。

[[擬似コード]]

// Client.js

var Socket = function(ip, port, name) { 
    this.ip = ip; 
    this.port = port; 
    this.name = name; 
    this._cbs = []; 
    this._poll(); 
}; 

// Call the server periodically for data. 
Socket.prototype._poll = function() { 
    var that = this; 
    // if the server does not return then call it again 
    var timer = setTimeout(function() { 
     this._poll(); 
    }, 5000); 
    $.ajax({ 
     type: "GET", 
     timeout: 5000, 
     data: { 
      name: this.name 
     }, 
     url: this.ip + ":" + this.port, 
     success: function(data) { 
      // server returned, kill the timer. 
      clearTimeout(timer); 
      // send the message to the callback. 
      for (var i = 0; i < that._cbs.length; i++) { 
       that._cbs[i](data); 
      } 
      // call the server again 
      that._poll(); 
     } 
    }); 
}; 

// Add a callback for a message event 
Socket.prototype.on = function(event, cb) { 
    if (event === "message") { 
     this._cbs.push(cb); 
    } 
}; 

// Send a message to the server 
Socket.prototype.send = function(message) { 
    $.ajax({ 
     data: { 
       message: message, 
       name: this.name 
     }, 
     type: "GET", 
     url: this.ip + ":" + this.port 
    }); 
}; 

var socket = new Socket('192.168.1.1', '8081', "Raynos"); 
socket.on("message", function(data) { 
    console.log(data); 
}); 
socket.send("Hello world!"); 

//より良いプッシュ技術はServer-side eventsだろう

var url = require("url"); 
var events = require("events"); 
// store messages for clients 
var clients = {}; 

var emitter = new events.EventEmitter(); 

http.createServer(function(req, res) { 
    // get query string data 
    var data = url.parse(req.url, true).query; 
    // if client is not initialized then initialize it. 
    if (data.name && !clients[data.name]) { 
     clients[data.name] = []; 
    } 
    // if you posted a message then add it to all arrays 
    if (data.message) { 
     for (var k in clients) { 
       clients[k].push(data.name + " : " + data.message); 
     } 
     // tell long pollers to flush new data. 
     emitter.emit("new-data"); 
    } else if (clients[data.name].length > 0) { 
     // else empty the clients array down the stream 
     for (var i = 0; i < clients[data.name].length; i++) { 
       res.write(clients[data.name].shift()); 
     }; 
     res.end(); 
    // long polling magic. 
    } else { 
     var cb = function() { 
       for (var i = 0; i < clients[data.name].length; i++) { 
        res.write(clients[data.name].shift()); 
       }; 
       res.end(); 
       // kill that timer for the response timing out. 
       clearTimeout(timer); 
     } 
     // when we get data flush it to client 
     emitter.once("new-data", cb); 
     var timer = setTimeout(function() { 
       // too long has passed so remove listener and end response. 
       emitter.removeListener(cb); 
       res.end(); 
     }, 4500); 
    } 
}).listen(8081); 

をserver.js。 example of it hereを参照してください。これはブラウザのサポートを必要とします(Chromeとオペラは私が思う)。

+1

最初にうわー、ありがとう!これはうまくいく方法ですが、長いポーリングでは膨大な数のクライアントでパフォーマンスの問題が発生するため、彗星サーバーは素晴らしいソリューションになりますが、node.jsで実装する方法はわかりません。http ://www.ape-project.org/ajax-push.htmlそれは私が欲しいものに似ていますが、ノードではありません:) – Adam

+1

@CIRKあなたがAPEに似たものを望むなら、socket.ioをインストールしてください。最初から書きたい場合は、socket.ioソースを読んでください。レコードのために私はノードのサーバープッシュを実装する方法を手がかりがありません:( – Raynos

+0

私はAPEもsocket.ioも望んでいません:P、私はsocket.ioのソースを見て、彼らがどのように動作しているか知りたいです。私はその論理を知らないので、O:S – Adam

0

長いポーリングの基本原則を知りたい場合は、this articleを参照してください。私は自分の長年の投票サーバーの特定の部分を要約し、どのように実装したのか、記事には他のリソースへのリンクも含まれています。少なくともポーリングがどのくらい長く続くかについてのより大きなイメージを与えるはずです。

node.jsでコーディングを楽しくし、既存のソリューションを使用しないようにするためには、ロジックを学びたいなら、最も簡単で基本的な実装からより複雑なものにステップバイステップを進めることをお勧めします。あなたが失敗する方法の中で最も確かな方法の1つなので、最初のショットから全体を構築しようとしないでください。

関連する問題