【问题标题】:socket_select() with 2 dimensional array带有二维数组的 socket_select()
【发布时间】:2012-05-14 21:07:35
【问题描述】:

我正在尝试让我的 PHP 服务器更高效一些。 我构建了一个名为 Client 的对象,其中包含已连接的客户端(与服务器有一个开放的套接字连接)信息,例如 nameid 等。

现在我有一组套接字连接和一组客户端对象。 当我提到一个连接时,我在我的客户端数组中搜索以找到与此连接匹配的正确客户端。 它工作得很好,但是效率有点低。对于服务器中的少量客户端你感觉不到,但我担心如果我有数千个连接它会减慢服务器的速度。

作为解决方案,我考虑了二维数组,但我在设计它时遇到了逻辑问题。

我可以这样做吗:

$clients = array();
$temp = array($newsock, new Client());
$clients[] = $temp;

我希望我的$clients[] 成为套接字,$clients[][] 成为客户端对象。 在$client 的每一行中,我将只有$client[$index][0],这将是我用于该连接的客户端对象。 我可以将其发送到socket_select() 函数吗?

【问题讨论】:

    标签: php sockets multidimensional-array


    【解决方案1】:

    你说你的客户对象中有一个id 属性。为什么不使用 id 作为两个数组的键?

    • 套接字连接数组
    • 客户端对象数组

    您甚至可以将连接和客户端对象保存在一个数组中,每个对象都使用我之前谈到的相同键 - 客户端 id

    无论如何,无论您决定在何处存储客户端连接对象,您都可以将其传递给所有相关的套接字函数 -

    • socket_select();
    • socket_accept();
    • socket_write();
    • 等等……

    关于您的服务器的效率,我实现了一些分叉以将数据广播到大量客户端(所有客户端都在聊天服务器的示例中)。

    这是我用于分叉广播的实现 -

    function broadcastData($socketArray, $data){
            global $db;
            $pid = pcntl_fork();
            if($pid == -1) {
                    // Something went wrong (handle errors here)
                    // Log error, email the admin, pull emergency stop, etc...
                    echo "Could not fork()!!";
            } elseif($pid == 0) {
                    // This part is only executed in the child
                    foreach($socketArray AS $socket) {
                            // There's more happening here but the essence is this
                            socket_write($socket,$msg,strlen($msg));
                            // TODO : Consider additional forking here for each client. 
                    }
                    // This is where the signal is fired
                    exit(0);
            }
            // The child process is now occupying the same database 
            // connection as its parent (in my case mysql). We have to
            // reinitialize the parent's DB connection in order to continue using it. 
            $db = dbEngine::factory(_dbEngine); 
    }
    

    上面的代码取自我之前的一个问题(即self answered)。
    Terminating zombie child processes forked from socket server

    如果您选择开始分叉进程,也许它可能会对您有所帮助。

    【讨论】:

    • 一般来说,使用 id 作为索引可能是一个很好的解决方案,唯一的问题是客户端对象的 id 属性是在建立套接字连接后由客户端发送的,并且它不是由服务器生成的。你能解释一下关于 pcntl_fork() 函数的更多信息吗?我对unix不太熟悉,也不太明白我在php.net中读到的解释
    • pcntl_fork()仅适用于类 unix 系统。它是创建一个独立于父进程的子进程以提高性能的过程——子进程可以处理特定的请求,让父服务器继续处理传入的数据。
    • 试一试是个好主意……回到我的问题,你有什么建议?我可以保留这样的数组:array(socket, new Client()) 并将其发送回 socket_select() 函数吗?或者我应该等待唯一的 id(在建立连接后从客户端接收)然后将套接字连接到对象?
    • 你不能将整个对象传递给`socket_select()`;只有实际的套接字连接。如果可以,那么可以 - 在建立连接后使用唯一 ID 并通过该 ID 检索连接。
    • 比每次都查找效率要高得多,对吧?
    猜你喜欢
    • 2018-09-23
    • 2012-04-05
    • 1970-01-01
    • 2016-08-09
    • 2013-02-13
    • 1970-01-01
    • 2015-10-08
    • 2013-04-28
    • 1970-01-01
    相关资源
    最近更新 更多