Swoole
Swoole 里也提供了一些直接操作底层 epoll/kqueue 事件循环的接口, 可将其他扩展创建的 socket,PHP 代码中 stream/socket 扩展创建的 socket 等加入到 Swoole 的 EventLoop 中.
文档: https://wiki.swoole.com/wiki/page/242.html
这里我也简单介绍一下.
基本使用
- swoole_tcp_server.php
- <?php
- /**
- * Created by PhpStorm.
- * User: 公众号: 飞鸿影的博客 (fhyblog)
- * Date: 2018/6/30
- */
- use Swoole\Event;
- $socket = stream_socket_server ("tcp://0.0.0.0:9201", $errno, $errstr);
- if (false === $socket ) {
- echo "$errstr($errno)\n";
- exit();
- }
- if (!$socket) die($errstr."--".$errno);
- // stream_set_blocking($socket,0); // 可以去掉, 没有涉及到 read 这个 socket
- echo "waiting client...\n";
- //accept 事件回调函数, 参数分别是 $fd
- function ev_accept($socket){
- global $master;
- $connection = stream_socket_accept($socket);
- // 参数的设置将会影响到像 fgets() 和 fread() 这样的函数从资源流里读取数据.
- // 在非阻塞模式下, 调用 fgets() 总是会立即返回; 而在阻塞模式下, 将会一直等到从资源流里面获取到数据才能返回.
- stream_set_blocking($connection, 0);// 如果不设置, 后续读取会阻塞
- $id = (int)$connection;
- echo "new Client $id\n";
- Event::add($connection, 'ev_read', null, SWOOLE_EVENT_READ);
- }
- //read 事件回调函数, 参数是 fd
- function ev_read($buffer)
- {
- $receive = '';
- // 循环读取并解析客户端消息
- while( 1 ) {
- $read = @fread($buffer, 2);
- // 客户端异常断开
- if($read === '' || $read === false){
- break;
- }
- $pos = strpos($read, "\n");
- if($pos === false)
- {
- $receive .= $read;
- // echo "received:".$read.";not all package,continue recdiveing\n";
- }else{
- $receive .= trim(substr ($read,0,$pos+1));
- $read = substr($read,$pos+1);
- switch ( $receive ){
- case "quit":
- echo "client close conn\n";
- // 关闭客户端连接
- Event::del($buffer);// 删除事件
- fclose($buffer);// 断开客户端连接
- break;
- default:
- // echo "all package:\n";
- echo $receive."\n";
- break;
- }
- $receive='';
- }
- }
- }
- Event::add($socket, 'ev_accept', null, SWOOLE_EVENT_READ);
- echo "start run...\n";
- // 进入事件循环
- Event::wait(); //PHP5.4 或更高版本不需要加此函数
- // 下面这句不会被执行
- echo "This code will not be executed.\n";
Event::add() 等方法也有对应的函数, 例如 swoole_event_add().
定时器
swoole 提供了两个定时器:
swoole_timer_tick 周期定时器, 面向对象写法: Timer::tick
swoole_timer_after 一次性定时器, 面向对象写法: Timer::after
swoole 定时器的精度是毫秒.
示例:
- <?php
- /**
- * Created by PhpStorm.
- * User: 公众号: 飞鸿影的博客 (fhyblog)
- * Date: 2018/6/30
- */
- use Swoole\Timer;
- Timer::after(1000, function(){
- echo time(). "hello\n";
- Timer::tick(1000, function($timer_id, $params){
- static $c = 0;
- echo time(). "hello $params $c\n";
- $c++;
- if($c> 5){
- Timer::clear($timer_id);
- }
- }, 'this is param');
- });
说明: Timer::after 回调函数没有参数, Timer::tick 回调函数参数是定时器 ID 及附加参数.
总结
我曾经查阅了 Workerman 的源码, 看到作者把常见的 Event(系统自带 Select,libevet,Event,Ev,Swoole) 进行了一次封装, 对外暴露了统一的接口 (add,del,loop), 大家有兴趣可以看看.
来源: https://www.cnblogs.com/52fhy/p/9261325.html