swoole的EventLoop学习

我们先使用php来写一个socket的服务端。先从最开始的模型开始将起逐步引申到为何要使用eventloop

1.最简单的socket服务端,直接按照官方文档来执行

<?php 

$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_bind($sock, "127.0.0.1",9511);

socket_listen($sock);

for ( ; ; ) {
    $conn = socket_accept($sock);

    $write_buffer = "hello word";

    socket_write($conn, $write_buffer);
   sleep(60);
    socket_close($conn);
}

执行telnet测试

然后再开一个telnet去请求,你会发现没有返回被阻塞了,这个就是这个原型的缺点。在一个tcp请求没有处理结束后会被阻塞。那这肯定不行。介绍下下一个多进程方式的服务器。

<?php
$sock = stream_socket_server("tcp://127.0.0.1:9511", $errno, $errstr);

$pids = [];

for ($i=0; $i<10; $i++) {

    $pid = pcntl_fork();
    $pids[] = $pid;

    if ($pid == 0) {
        for ( ; ; ) {
            $conn = stream_socket_accept($sock);

            $write_buffer = "hello!world";

            fwrite($conn, $write_buffer);
            sleep(60);
            fclose($conn);
        }

        exit(0);
    }

}

foreach ($pids as $pid) {
    pcntl_waitpid($pid, $status);
}

运行后开启2个telnet客户端,你会发现即使是一个客户端还没关闭连接,另外的也能发起请求拿到返回值。但是这样也会有新的问题。io还是压力很大,要解决问题的在不能优化逻辑代码的情况下,只有多添加进程数来解决。但是进程是很昂贵的资源。那就引申出了php的libevent。这里就不做介绍了,我们直接使用swoole的eventloop. 其实swoole的server已经是这种模型了,所以就直接贴一个官方的示例

$fp = stream_socket_client("tcp://www.qq.com:80", $errno, $errstr, 30);
fwrite($fp,"GET / HTTP/1.1\r\nHost: www.qq.com\r\n\r\n");

swoole_event_add($fp, function($fp) {
    $resp = fread($fp, 8192);
    //socket处理完成后,从epoll事件中移除socket
    swoole_event_del($fp);
    fclose($fp);
});
echo "Finish\n";  //swoole_event_add不会阻塞进程,这行代码会顺序执行

就是使用了swoole_event_add添加了读的事件回调,在读取完成后直接删除掉时间回调。一次请求就结束了。

猜你喜欢

转载自www.cnblogs.com/gavinjunftd/p/9145564.html
今日推荐