php libev扩展使用

       在WorkerMan源码分析 - 实现最简单的原型文章中提到了libevent网络库,前者和libev都是事件驱动编程库高性能。简单说libev对libevent做了改进和精简。libevent使用全局变量,导致非线程安全。它的watcher结构也过大,把I/O、计时器、信号句柄整合在一起。而且(作者认为)libevent的附加组件如http和dns库都实现不好,且有安全问题。libev对这些地方做了改进,避免使用全局变量,拆分watcher等。另外libev去掉了外部库(比如http和dns),只专注于事件驱动服务,所以更精简。

安装libev扩展

地址:https://pecl.php.net/package/ev

实例

定时器实现

<?php
//定时器的实现,2秒后每2秒触发1次注册的事件

$loop = new EvLoop();

function timers()
{
    echo date("Y-m-d H:i:s") . "
";
}

//$event = $loop->timer(2,0,'timers');
$event = $loop->timer(2,2,'timers');
$loop->run();

结果如下:

2018-04-25 16:57:54
2018-04-25 16:57:55
2018-04-25 16:57:56
2018-04-25 16:57:57

基于事件循环 异步io 的socket读写

 1 <?php
 2 $loop = new EvLoop();
 3 $arr = [];
 4 $data = "hello world
";
 5 
 6 function add($fd,$ev,$func){
 7     global $arr,$loop;
 8     $func = getStreamListenerClosure($fd,$func);
 9     //创建观察者监听io $ev事件
10     $event = $loop->io($fd,$ev,$func);
11     $arr[posix_getpid()][(int)$fd] = $event;
12 }
13 
14 //返回闭包
15 function getStreamListenerClosure($stream, $listener){
16     return function () use ($stream,$listener){
17         call_user_func($listener,$stream);
18     };
19 }
20 
21 //
22 function baseRead($socket){
23     $buffer = @fread($socket, 2);
24 
25     if ($buffer == "
"){
26         //结尾
27         fclose($socket) && removeStream($socket);
28     } else {
29         echo $buffer;
30     }
31 }
32 
33 //
34 function baseWrite($socket){
35 
36     global $data;
37 
38     $written = fwrite($socket, $data,1);
39     if ($written === strlen($data)) {
40         fclose($socket);
41         removeStream($socket);
42     } else {
43         $data = substr($data, $written);
44     }
45 
46 }
47 
48 //停止指定事件并销魂指定流资源
49 function removeStream($stream){
50 
51     global $arr,$loop;
52     $key = (int)$stream;
53     $pid = posix_getpid();
54 
55     if (!isset($arr[$pid][$key]))
56         return;
57 
58     $arr[$pid][$key]->stop();
59     unset($arr[$pid][$key]);
60 }
61 
62 function acceptConnection($socket){
63 
64     $new_socket = @stream_socket_accept($socket);
65     if (!$new_socket) {
66         return;
67     }
68 
69     stream_set_blocking($new_socket,false);
70     stream_set_read_buffer($new_socket, 0);
71 
72     //add($new_socket,Ev::READ,'baseRead');
73     add($new_socket,Ev::WRITE,'baseWrite');
74 
75 }
76 
77 //定时器
78 function timers()
79 {
80     echo date("Y-m-d H:i:s") . "
";
81 }
82 
83 $socketmain = stream_socket_server('tcp://127.0.0.1:7777');
84 //非阻塞
85 stream_set_blocking($socketmain,false);
86 
87 add($socketmain,Ev::READ,'acceptConnection');
88 
89 $event = $loop->timer(2,2,'timers');
90 
91 $loop->run();
92 
93 /*
94 while (true){
95     //EV::RUN_ONCE 事件只触发1次
96     $loop->run(EV::RUN_ONCE);
97 }
98 */

利用telnet测试,具体参考WorkerMan源码分析 - 实现最简单的原型文章。

原文地址:https://www.cnblogs.com/loveyouyou616/p/8945863.html