PHP Socket 服务器与 node.js:网络聊天

Posted

技术标签:

【中文标题】PHP Socket 服务器与 node.js:网络聊天【英文标题】:PHP Socket Server vs node.js: Web Chat 【发布时间】:2011-06-02 04:07:36 【问题描述】:

我想使用长期持有的 HTTP 请求 (Comet)、ajax 和 websockets(取决于所使用的浏览器)来编写一个 HTTP WebChat。用户数据库在 mysql 中。聊天是用 php 编写的,除了聊天流本身也可以用 javascript (node.js) 编写:

我不想为每个用户启动一个 php 进程,因为没有好的方法可以在这些 php 子项之间发送聊天消息。 所以我考虑用 PHP 或 node.js 编写一个自己的套接字服务器,它应该能够处理超过 1000 个连接(聊天用户)。作为一个纯粹的 Web 开发人员 (php),我对套接字不太熟悉,因为我通常让 Web 服务器关心连接。聊天消息不会保存在磁盘或 mysql 中,而是作为数组或对象保存在 RAM 中以获得最佳速度。

据我所知,没有办法在单个 php 进程(套接字服务器)中同时处理多个连接,但是您可以接受大量套接字连接并在循环中连续处理它们(读取和写入;传入消息 -> 写入所有套接字连接)。问题在于,大约 1000 个用户很可能会出现延迟,并且 mysql 操作可能会减慢整个过程,进而影响所有用户。

我的问题是:node.js 可以处理性能更好的套接字服务器吗? Node.js 是基于事件的,但我不确定它是否可以同时处理多个事件(那不需要多线程吗?)或者是否只有一个事件队列。使用事件队列就像 php: process user after user。

我还可以为每个聊天室生成一个 php 进程(用户少得多),但是 afaik 有单线程 IRC 服务器也能够处理数千个用户。 (用 c++ 或其他编写)所以也许它也可以在 php 中。

我更喜欢 PHP 而不是 Node.js,因为这样该项目将是 php-only,而不是编程语言的混合。但是,如果 Node 可以同时处理连接,我可能会选择它。

【问题讨论】:

【参考方案1】:

我回答的另一个主题可以帮助您并轻松满足您的需求 => How to use redis PUBLISH/SUBSCRIBE with nodejs to notify clients when data values change?

【讨论】:

【参考方案2】:

JavaScript,或者在本例中是 Node 使用的引擎 V8,是 设计 单线程的。所以是的,只有一个事件队列。

但归根结底,这不是问题,总会先发生一些事情,除非您使用多个处理器,即使那样,您也很可能只有一个网卡...一个路由器……你明白了。此外,使用 1000 多个线程...不是一个好主意,扩展性很差,而且您会发现自己处于并发HELL中。

1000 个聊天用户,对于 Node.js 来说,完全没有问题

我可以告诉你一个非常基本的想法,你将如何设置它,这个简单的香草聊天东西可以通过 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);

这里没有任何魔法(除了使用closures),您不必使用原始套接字编程,也不会遇到任何并发问题。并且你会了解到一些最新的热点 ;)

我建议您观看我们的 Node.js 标签 wiki 上列出的一些演讲,以更好地了解 Node.js 的工作原理。

【讨论】:

感谢您的代码。上周我在 PHP 中写的几乎相同(即使名称 !== '' 部分相同),所以我现在将检查它在 PHP 中的速度是否与在 node.js 中一样快,所以我不需要使用两种语言,尽管 node.js 很好也很简单,因为我多年来一直将它用于客户端脚本(jquery 等)。 @Eliasdx 你每个基准node.js vs php 吗?我很好奇结果可能是什么。 @Eliasdx 有这方面的消息吗?我希望自己创建一个聊天室,并且很想知道您的发现。我个人更喜欢 PHP。

以上是关于PHP Socket 服务器与 node.js:网络聊天的主要内容,如果未能解决你的问题,请参考以下文章

Node.js + Socket IO + Apache + PHP 便宜的网络服务器? [关闭]

使用 Node.js/socket.io 和 php/mysql 的 Web 应用程序

如何在 node.js 服务器上的 PHP Web 服务器和 Socket.io 之间创建握手?

PHP -> Node.js 传输/桥接

与 Node.js / Socket.io 服务器共享 Laravel 会话

显示在线关注者的最佳方式是啥,node.js/socket.io 和 Redis