已掉线,重新登录

首页 > 绿虎论坛 > 历史版块 > 编程 > PHP > 教程

标题: 纯手撸PHP在 php-client模式下做http服务器,超强性能

作者: @Ta

时间: 2022-03-01发布,2022-03-01修改

点击: 4587

image.png

## 纯手撸一个 单进程下的socket IO复用

### 可以使用pcntl_fork 把下面的代码进行多进程创建,提高php在服务器上的CPU利用率
<?php

class SocketServer
{

    public $socket;

    public $all_sockets = [];

    public function __construct(string $address)
    {
        //创建监听socket服务 资源句柄 ,,resource|false
        $this->socket = \stream_socket_server($address, $php_errorcode, $php_errormsg);

        if ($this->socket == false) {
            throw new \Exception('创建失败!', $php_errorcode, $php_errormsg);
        }

        \stream_set_blocking($this->socket, false);

        //当前初始化的第一个socket服务 资源句柄放入 资源池
        $this->all_sockets[intval($this->socket)] = $this->socket;
        echo ('=== 服务器启动|' . $address.PHP_EOL);
    }

    public function run()
    {
        //死循环
        while (true) {
            $write=$except=null;
            $allSocket=$this->all_sockets;
            \stream_select($allSocket, $write, $except, 60);

            foreach ($allSocket as $index => $socket) {
                //如果 streamsocket 服务句柄 == 当前socket资源池的id,说明有新连接
                if ($this->socket === $socket) {
                    // 接受由 stream_socket_server() 创建的套接字连接 timeout/覆盖默认的套接字接受的超时时限。输入的时间需以秒为单位
                    // resource|false
                    $new_conn_socket = \stream_socket_accept($this->socket);
                    if ($new_conn_socket == false) {
                        //可能是建立连接异常
                        continue;
                    }
                    $this->onConn($new_conn_socket);
                    $this->all_sockets[intval($new_conn_socket)] = $new_conn_socket;
                    echo '=== 新连接建立'.(int)($new_conn_socket).PHP_EOL;
                } else {
                    //如果不是新的连接,则看看有无数据过来,读取长度 65536
                    $buff = fread($socket, 0xFFFF);
                    // 不能是 == ''
                    if ($buff === '' || $buff === false) {
                        //客户端已断开
                        echo '=== 断开连接'.intval($socket).PHP_EOL;
                        $this->onClose($socket);
                        unset($this->all_sockets[intval($socket)]);
                        fclose($socket);
                        continue;
                    }
                    //处理发来的数据
                    $this->onMessage($socket, $buff);
                }
            }
        }
    }


    public function onConn(mixed $socket)
    {

    }

    public function onClose(mixed $socket)
    {
    }

    public function onMessage(mixed $socket, $buff)
    {
        $body = 'hello word';
        $header = [
            'HTTP/1.1 200 OK',
            'Connection: keep-alive',
            'Niubi: test123',
            'Content-length:' . strlen($body)
        ];
        $header_string = \implode(chr(0x0D) . chr(0x0A), $header);

        $data = $header_string . chr(0x0D) . chr(0x0A) . chr(0x0D) . chr(0x0A) . $body;


//        echo '用户数据:'.$buff.PHP_EOL;
        fwrite($socket, $data);

        unset($this->all_sockets[intval($socket)]);
        fclose($socket);
    }

}


$a = new SocketServer('tcp://0.0.0.0:88');
$a->run();;






[隐藏样式|查看源码]


『回复列表(8|隐藏机器人聊天)』

1. 支持
(/@Ta/2022-03-01 15:27//)

2.

fork + SO_REUSEPORT = 多核优化轻松搞定

https://phpor.net/blog/post/3139

(/@Ta/2022-03-01 16:26//)

3. @胡椒舰长https://www.workerman.net/doc/webman/ 了解一下
(/@Ta/2022-03-01 16:43//)

4.
用户被禁言,发言自动屏蔽。
(/@Ta/2022-03-01 17:00//
被禁言
)

5. @无期徒刑,相对于宝塔 nginx+php-fpm 效率提高太多了。可能唯一的缺点就是 技术不好或者不规范的写法容易在常驻内存模式下,造成的内存泄露。
虽然现在workerman仍然是 多进程阻塞但是
workerman仓库里有一份是基于多线程的`parallel`的初代版本,作者没舍得删除。
(/@Ta/2022-03-01 18:18//)

7.
小米MIX2s(白)
(/@Ta/2022-03-02 09:48//)

9.
层主 @胡椒舰长 于 2023-07-04 20:09 删除了该楼层。
(/@Ta/2022-03-03 16:57//
被锁定
)

11. @卷心菜,既然有swoole了为什么还要考虑php的pcntl
(/@Ta/2022-03-03 17:01//)

回复需要登录

6月30日 00:48 星期一

本站由hu60wap6驱动

备案号: 京ICP备18041936号-1