Node.JS:如何创build一个HTTP聊天服务器?

使用networkingstream对象与TCP工程伟大(作为presetend在node.js介绍video ),但我应该如何做到这一点在HTTP?

有没有办法访问http.createServer()内的套接字/客户端? 或者有什么办法呢? 我试图从官方节点聊天演示 源代码中找出解决scheme,但我不明白。

我了解客户端JS,但是我(作为客户端)通过AJAX发送消息到服务器端JS后发生了什么? 我怎样才能发送给服务器上的其他客户呢?

请注意,我不想学习过程的逻辑,所以我不想使用socket.io或任何其他框架,库,模块。

非常感谢您的帮助!

理想情况下,你只是使用WebSockets但替代scheme是ajax长轮询。

您可以使用称为长轮询的技术来进行聊天。 这意味着您向服务器发出(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.js

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

更好的推技术将是服务器端事件 。 在这里看到一个例子 。 这确实需要浏览器的支持,虽然(我认为铬和歌剧)。

一种做法是让客户“订阅”一个充当消息分发者的渠道。 一旦订阅,客户端接收到发送到该频道的每个消息的副本。

许多节点聊天服务都依赖于redis的pubsubfunction来处理从一个到多个客户端的消息分配。 如果你想“自己动手”,理解redis如何解决这个问题将是一个很好的开始。

如果你想知道长轮询的基本原则,那么试着看这篇文章 。 我在那里总结了我自己的长轮询服务器的某些部分,我是如何实现它们的,这篇文章还包含了其他资源的链接。 它应该至less给你投票多长时间的更大的图片。

如果你想学习逻辑,以便对node.js有一些编码的乐趣,而不是使用现有的解决scheme,那么我会build议从最简单和基本的实现一步步到更复杂的东西。 不要试图从第一枪开始构build整个事情,因为这是如何失败的最可靠的方法之一。