PHP Socket Server 与 node.js:网络聊天
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4573186/
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
PHP Socket Server vs node.js: Web Chat
提问by Eliasdx
I want to program a HTTP WebChat using long-held HTTP requests (Comet), ajax and websockets (depending on the browser used). Userdatabase is in mysql. Chat is written in PHP except maybe the chat stream itself which could also be written in javascript (node.js):
我想使用长期保持的 HTTP 请求(Comet)、ajax 和 websockets(取决于所使用的浏览器)来编程 HTTP WebChat。用户数据库在 mysql 中。聊天是用 PHP 编写的,除了聊天流本身也可以用 javascript (node.js) 编写:
I don't want to start a php process per user as there is no good way to send the chat messages between these php childs. So I thought about writing an own socket server in either PHP or node.js which should be able to handle more then 1000 connections (chat users). As a purely web developer (php) I'm not much familiar with sockets as I usually let web server care about connections. The chat messages won't be saved on disk nor in mysql but in RAM as an array or object for best speed.
我不想为每个用户启动一个 php 进程,因为没有好的方法可以在这些 php 孩子之间发送聊天消息。所以我想用 PHP 或 node.js 编写一个自己的套接字服务器,它应该能够处理超过 1000 个连接(聊天用户)。作为一个纯粹的 web 开发人员 (php),我对套接字不太熟悉,因为我通常让 web 服务器关心连接。聊天消息不会保存在磁盘或 mysql 中,而是作为数组或对象保存在 RAM 中以获得最佳速度。
As far as I know there is no way to handle multiple connections at the same time in a single php process (socket server), however you can accept a great amount of socket connections and process them successive in a loop (read and write; incoming message -> write to all socket connections). The problem is that there will most-likely be a lag with ~1000 users and mysql operations could slow the whole thing down which will then affect all users.
据我所知,无法在单个 php 进程(套接字服务器)中同时处理多个连接,但是您可以接受大量套接字连接并在循环中连续处理它们(读取和写入;传入消息 -> 写入所有套接字连接)。问题是,大约 1000 个用户很可能会出现延迟,而 mysql 操作可能会减慢整个过程,进而影响所有用户。
My question is: Can node.js handle a socket server with better performance? Node.js is event-based but I'm not sure if it can process multiple events at the same time (wouldn't that need multi-threading?) or if there is just an event queue. With an event queue it would be just like php: process user after user.
我的问题是:node.js 可以处理性能更好的套接字服务器吗?Node.js 是基于事件的,但我不确定它是否可以同时处理多个事件(不需要多线程吗?)或者是否只有一个事件队列。有了事件队列,它就像 php: 一个接一个地处理用户。
I could also spawn a php process per chat room (much less users) but afaik there are singlethreaded IRC servers which are also capable to handle thousands of users. (written in c++ or whatever) so maybe it's also possible in php.
我还可以为每个聊天室生成一个 php 进程(用户要少得多),但是我知道有单线程 IRC 服务器,它们也能够处理数千个用户。(用 C++ 或其他语言编写)所以也许在 php 中也是可能的。
I would prefer PHP over Node.js because then the project would be php-only and not a mixture of programming languages. However if Node can process connections simultaneously I'd probably choose it.
我更喜欢 PHP 而不是 Node.js,因为这样该项目将只使用 php 而不是编程语言的混合。但是,如果 Node 可以同时处理连接,我可能会选择它。
回答by Ivo Wetzel
JavaScript, or in this case V8 which is the engine that Node is using, is by designsingle threaded. So yes there's just an event queue.
JavaScript,或者在这种情况下,V8 是 Node 使用的引擎,设计是单线程的。所以是的,只有一个事件队列。
But in the end, that's nota problem, something's always gonna happen first, unless you're using multiple processors, and even then, you will most likely only have one network card... one router... you get the idea. Also, using 1000+ threads... not a good idea, scales badly, and you will find yourself in a concurrency HELL.
但最终,这不是问题,总有一些事情会先发生,除非您使用多个处理器,即便如此,您也很可能只有一张网卡……一个路由器……您明白了。此外,使用 1000 多个线程......不是一个好主意,扩展性很差,你会发现自己处于并发HELL 中。
1000 chat users, that will be no problem at allfor Node.js.
1000 个聊天用户,这对 Node.js 来说完全没有问题。
I can give you a pretty basicidea how you would set it up, this plain vanilla chat thingy works over telnet, it has.. no features, but it works:
我可以给你一个非常基本的想法,你将如何设置它,这个普通的聊天工具可以通过 telnet 工作,它有..没有功能,但它有效:
var net = require('net'); // require the net module
var users = []; // keep track of the users
// setup a new tcp socket server
net.createServer(function(socket) { // provide a callback in case a new connection gets
// established, socket is the socket object
// keep track of this users names, via use of closures
var name = '';
// ask the new user for a name
socket.write('Enter a Name(max 12 chars): ');
// register a callback on the socket for the case of incoming data
socket.on('data', function(buffer) { // buffer is a Buffer object containing the data
if (name !== '') { // in case this user has a name...
// send out his message to all the other users...
for(var i = 0; i < users.length; i++) {
if (users[i] !== socket) { // ...but himself
users[i].write(name + ': '
+ buffer.toString('ascii').trim()
+ '\r\n');
}
}
// otherwise take the data and use that as a name
} else {
name = buffer.toString('ascii').substring(0, 12).trim().replace(/\s/g, '_');
socket.write('> You have joined as ' + name + '\r\n');
// push this socket to the user list
users.push(socket);
for(var i = 0; i < users.length; i++) {
if (users[i] !== socket) {
users[i].write('> ' + name + ' has joined' + '\r\n');
}
}
}
});
// another callback for removing the user aka socket from the list
socket.on('end', function() {
users.splice(users.indexOf(socket), 1);
});
// bind the server to port 8000
}).listen(8000);
There's no magic involved in here (besides the use of a closures), you don't have to do with raw socket programming and you won't have any concurrency problems. And you learn some of the latest hotness ;)
这里没有任何魔法(除了使用了闭包),您不必处理原始套接字编程,也不会有任何并发问题。你会学到一些最新的热点 ;)
I recommend that you watch some of the talks that are listed on our Node.jstag wiki, to get a better grasp of how Node.js works.
我建议您观看我们的Node.js标签 wiki上列出的一些演讲,以更好地了解 Node.js 的工作原理。
回答by Alfred
Another topic which I answered which could help you and will easily scale to your needs => How to use redis PUBLISH/SUBSCRIBE with nodejs to notify clients when data values change?
我回答的另一个主题可以帮助您并且可以轻松地根据您的需求进行扩展 =>如何在数据值更改时使用 redis PUBLISH/SUBSCRIBE 和 nodejs 来通知客户端?