【问题标题】:Passing a live socket between two PHP scripts在两个 PHP 脚本之间传递一个活动套接字
【发布时间】:2013-12-16 00:13:22
【问题描述】:

我正在用 PHP 编写一个 websocket 服务器,它需要能够处理大量并发连接。我目前正在使用 socket_select 函数来允许它处理它们,但是当向客户端发送大量数据时,这仍然会阻止所有其他连接。有没有办法让主脚本接受传入的套接字,然后启动第二个 PHP 脚本(显然是以非阻塞方式)并将客户端套接字传递给该脚本进行处理?我知道这在 C 中是可能的,但遗憾的是,代码库无法进行迁移。

*服务器仅在 Unix 堆栈上运行,不需要与 MS 兼容的解决方案。

【问题讨论】:

  • 你也许可以让这个工作......但是,你是否考虑过一个更容易做到这一点的平台,比如 Node.js?
  • 是的,我开始认为我必须修改很久以前编写的 C 程序才能使其工作。我的意思是,这是我想要追求的一个有趣的项目,但此时我真的没有时间让自己加快使用新语言的套接字等并最终得到一个安全的解决方案。

标签: php multithreading sockets asynchronous websocket


【解决方案1】:

我目前正在使用 socket_select 函数来允许它处理它们,但是当向客户端发送大量数据时,这仍然会阻塞所有其他连接。

那么不要一次发送所有数据。如果你打算这样做

socket_write ($mysocket, $mybuffer, 10000000);

那么是的,您必须等到所有 1000 万字节都已发送出去。但是,您可以结合非阻塞套接字使用socket_select$write 数组来检查您是否可以写入套接字。每次socket_select 说你有一个“去!”在套接字上,写入数据直到socket_write 开始抱怨(即返回 FALSE 或小于指定长度)。这将使套接字的发送缓冲区保持最佳状态。

缺点是您必须准确跟踪您在输出缓冲区中的位置;另外,在您写入所有数据后关闭套接字上的非阻塞,否则socket_select 将继续触发(假设您要发送多个大数据块)。

【讨论】:

    【解决方案2】:

    结果与您在 C - fork() 中使用的答案相同。当你分叉时,所有打开的文件和端口的状态都会被保留,因此子进程可以读取由其父进程打开的端口(这与现代网络服务器为每个进入的客户端连接分离工作线程的方式相同)它确实需要使用默认禁用的 pcntl(过程控制)模块,应该谨慎使用,但它可以工作:

    if($verbose)
        echo "Connected Client from $remoteaddy to $localaddy\n";
    echo "Forking...";
    $pid = pcntl_fork(); // you're bringing children into this world, just to kill them in a few seconds. You monster. 
    if($pid==0){
                $p = posix.getpid();
        echo "PID OF CHILD: $p\n";
        //in child process. Send a handshake and wait for the callback from the WebSockets library 
        $this->send($client, "Thank you for contacting myAwesomeServer.com! I'm slave #{$p}, and I'll be your host today");  
    }else if($pid>0){
        $childWorkers[]=$pid;
        echo "[ OK ]\n";
        $this->disconnect($client->socket, false); //disconnect the clients socket from the master thread, so only the child thread is talking to the client
    
    }else if($pid==-1){
        echo "[FAIL] unable to create child worker\n";
    }
    

    注意!!这种方法纯粹是学术性的,仅当您没有足够的时间学习更合适的语言时才应将其用于小型“宠物”项目(就个人而言,我对 C 的了解足以 fork(),但我缺乏知识它的字符串操作功能无疑会在服务器上留下一个巨大的安全漏洞)。我不确定 Zend 引擎是如何执行此 pcntl_fork() 的,但我想这个怪物的内存映像将是等效 C 代码大小的许多倍。

    【讨论】:

    • 为什么是学术性的? PHP 不适合 websocket-server 吗?记住在执行 Fork 时使用的 Copy-on-write。 PHP 的 fork 是通过引擎盖下的相同系统 fork 实现的。
    猜你喜欢
    • 2017-10-16
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    • 2015-03-10
    • 1970-01-01
    相关资源
    最近更新 更多