├── public
└── test.html
├── _lib
├── Workerman_linux
│ ├── .gitignore
│ ├── Lib
│ │ ├── Constants.php
│ │ └── Timer.php
│ ├── composer.json
│ ├── MIT-LICENSE.txt
│ ├── Protocols
│ │ ├── Frame.php
│ │ ├── Game.php
│ │ ├── ProtocolInterface.php
│ │ ├── Text.php
│ │ └── Http
│ │ │ └── mime.types
│ ├── Events
│ │ ├── EventInterface.php
│ │ ├── React
│ │ │ ├── ExtEventLoop.php
│ │ │ ├── LibEventLoop.php
│ │ │ └── StreamSelectLoop.php
│ │ ├── Ev.php
│ │ ├── Event.php
│ │ ├── Libevent.php
│ │ └── Select.php
│ ├── Connection
│ │ ├── ConnectionInterface.php
│ │ └── UdpConnection.php
│ └── Autoloader.php
├── Workerman_win
│ ├── .gitignore
│ ├── Lib
│ │ ├── Constants.php
│ │ └── Timer.php
│ ├── Protocols
│ │ ├── Frame.php
│ │ ├── Game.php
│ │ ├── ProtocolInterface.php
│ │ ├── Text.php
│ │ └── Http
│ │ │ └── mime.types
│ ├── Autoloader.php
│ ├── Events
│ │ ├── EventInterface.php
│ │ ├── React
│ │ │ ├── ExtEventLoop.php
│ │ │ ├── LibEventLoop.php
│ │ │ └── StreamSelectLoop.php
│ │ ├── Ev.php
│ │ ├── Event.php
│ │ ├── Libevent.php
│ │ ├── React.php
│ │ └── Select.php
│ └── Connection
│ │ ├── ConnectionInterface.php
│ │ ├── UdpConnection.php
│ │ └── AsyncUdpConnection.php
├── ape
│ ├── base
│ │ ├── BaseController.php
│ │ ├── MYSQL
│ │ └── DBBase.php
│ ├── session
│ │ └── Session.php
│ ├── constant.php
│ ├── register.php
│ ├── http
│ │ ├── mime.types
│ │ └── Sendfile.php
│ ├── Router.php
│ ├── helper.php
│ ├── view
│ │ └── View.php
│ ├── StatisticClient.php
│ └── ApeWeb.php
├── Autoloader.php
└── GlobalData
│ ├── Server.php
│ └── Client.php
├── z_api
├── views
│ └── test2.html
├── filter.php
├── filter
│ └── Filter.php
└── controller
│ └── TestController.php
├── config
├── database.php
├── filter.php
└── config.php
├── main
├── model
└── Admin.php
├── start_app.php
├── start_filemonitor.php
└── README.md
/public/test.html:
--------------------------------------------------------------------------------
1 | hello ape
2 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/.gitignore:
--------------------------------------------------------------------------------
1 | logs
2 | .buildpath
3 | .project
4 | .settings
5 | .idea
--------------------------------------------------------------------------------
/_lib/Workerman_win/.gitignore:
--------------------------------------------------------------------------------
1 | .project
2 | .buildpath
3 | .settings/org.eclipse.php.core.prefs
--------------------------------------------------------------------------------
/z_api/views/test2.html:
--------------------------------------------------------------------------------
1 | test2
2 |
3 | {foreach $admins k2=>n2}
4 | {$n2['name']}
5 | {/foreach}
6 |
--------------------------------------------------------------------------------
/z_api/filter.php:
--------------------------------------------------------------------------------
1 | AddFilter ( "/api", \z_api\filter\Filter::login( $app ) );
4 |
--------------------------------------------------------------------------------
/_lib/ape/base/BaseController.php:
--------------------------------------------------------------------------------
1 | array(
4 | 'host' => "127.0.0.1",
5 | 'port' => "3306",
6 | 'username' => "www",
7 | 'password' => "www",
8 | 'db_name' => "test",
9 | 'cache' => false
10 | )
11 | );
12 |
--------------------------------------------------------------------------------
/config/filter.php:
--------------------------------------------------------------------------------
1 | AddFilter ( "/", function(){
8 | var_dump("全局拦截器-我在根目录下的filter.php中");
9 | return true;
10 | } );
11 |
12 | // 自定义404
13 | $apeWeb->on404 = function () {
14 | $this->send ( "page not found!" );
15 | };
16 |
--------------------------------------------------------------------------------
/z_api/controller/TestController.php:
--------------------------------------------------------------------------------
1 | select ( '*' )->from ( static::$table )->where ( 'phone= :phone' )->where ( 'password= :password' )->where ( 'deleted_at is null' )->bindValues ( array (
19 | 'phone' => $phone,
20 | 'password' => $password
21 | ) )->query ();
22 | if (is_array ( $admins) && count ( $admins) > 0) {
23 | return $admins[0];
24 | } else {
25 | return null;
26 | }
27 | }
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/config/config.php:
--------------------------------------------------------------------------------
1 | "8081",
4 | // session模式 file存文件 database存入数据库
5 | "session_type" => "database",
6 | "session_name" => "ape_session",
7 | // 进程名字
8 | "worker_name" => "worker_ape",
9 | // 开启多少个进程,windows下只能开启一个
10 | "worker_count" => 1,
11 | // 每个进程最多接待多少个访客
12 | "max_request" => 10000,
13 | // 默认controller
14 | "default_module" => "api",
15 | // 默认controller
16 | "default_controller" => "Test",
17 | // 默认方法
18 | "default_method" => "test1",
19 | // 系统日志文件位置,相对与根目录下的log目录
20 | "logFile" => "info.log",
21 | // 重定向标准输出,即将所有echo、var_dump等终端输出写到对应文件中
22 | // 注意 此参数只有在以守护进程方式运行时有效
23 | "stdoutFile" => "echo.log"
24 | );
25 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Lib/Constants.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 |
15 | // Date.timezone
16 | if (! ini_get ( 'date.timezone' )) {
17 | date_default_timezone_set ( 'Asia/Shanghai' );
18 | }
19 | // Display errors.
20 | ini_set ( 'display_errors', 'on' );
21 | // Reporting all.
22 | error_reporting ( E_ALL );
23 |
24 | // For onError callback.
25 | define ( 'WORKERMAN_CONNECT_FAIL', 1 );
26 | // For onError callback.
27 | define ( 'WORKERMAN_SEND_FAIL', 2 );
28 |
29 | // Compatible with php7
30 | if (! class_exists ( 'Error' )) {
31 | class Error extends Exception {
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Lib/Constants.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 |
15 | // Date.timezone
16 | if (!ini_get('date.timezone')) {
17 | date_default_timezone_set('Asia/Shanghai');
18 | }
19 | // Display errors.
20 | ini_set('display_errors', 'on');
21 | // Reporting all.
22 | error_reporting(E_ALL);
23 |
24 | // Reset opcache.
25 | if (function_exists('opcache_reset')) {
26 | opcache_reset();
27 | }
28 |
29 | // For onError callback.
30 | define('WORKERMAN_CONNECT_FAIL', 1);
31 | // For onError callback.
32 | define('WORKERMAN_SEND_FAIL', 2);
33 |
34 | // Compatible with php7
35 | if(!class_exists('Error'))
36 | {
37 | class Error extends Exception
38 | {
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name" : "workerman/workerman",
3 | "type" : "library",
4 | "keywords": ["event-loop", "asynchronous"],
5 | "homepage": "http://www.workerman.net",
6 | "license" : "MIT",
7 | "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.",
8 | "authors" : [
9 | {
10 | "name" : "walkor",
11 | "email" : "walkor@workerman.net",
12 | "homepage" : "http://www.workerman.net",
13 | "role": "Developer"
14 | }
15 | ],
16 | "support" : {
17 | "email" : "walkor@workerman.net",
18 | "issues": "https://github.com/walkor/workerman/issues",
19 | "forum" : "http://wenda.workerman.net/",
20 | "wiki" : "http://doc3.workerman.net/index.html",
21 | "source": "https://github.com/walkor/workerman"
22 | },
23 | "require": {
24 | "php": ">=5.3"
25 | },
26 | "suggest": {
27 | "ext-event": "For better performance."
28 | },
29 | "autoload": {
30 | "psr-4": {"Workerman\\": "./"}
31 | },
32 | "minimum-stability":"dev"
33 | }
34 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/MIT-LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2009-2015 walkor and contributors (see https://github.com/walkor/workerman/contributors)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/_lib/Autoloader.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Protocols;
15 |
16 | use Workerman\Connection\TcpConnection;
17 |
18 | /**
19 | * Frame Protocol.
20 | */
21 | class Frame
22 | {
23 | /**
24 | * Check the integrity of the package.
25 | *
26 | * @param string $buffer
27 | * @param TcpConnection $connection
28 | * @return int
29 | */
30 | public static function input($buffer, TcpConnection $connection)
31 | {
32 | if (strlen($buffer) < 4) {
33 | return 0;
34 | }
35 | $unpack_data = unpack('Ntotal_length', $buffer);
36 | return $unpack_data['total_length'];
37 | }
38 |
39 | /**
40 | * Decode.
41 | *
42 | * @param string $buffer
43 | * @return string
44 | */
45 | public static function decode($buffer)
46 | {
47 | return substr($buffer, 4);
48 | }
49 |
50 | /**
51 | * Encode.
52 | *
53 | * @param string $buffer
54 | * @return string
55 | */
56 | public static function encode($buffer)
57 | {
58 | $total_length = 4 + strlen($buffer);
59 | return pack('N', $total_length) . $buffer;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Protocols/Frame.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Protocols;
15 |
16 | use Workerman\Connection\TcpConnection;
17 |
18 | /**
19 | * Frame Protocol.
20 | */
21 | class Frame
22 | {
23 | /**
24 | * Check the integrity of the package.
25 | *
26 | * @param string $buffer
27 | * @param TcpConnection $connection
28 | * @return int
29 | */
30 | public static function input($buffer, TcpConnection $connection)
31 | {
32 | if (strlen($buffer) < 4) {
33 | return 0;
34 | }
35 | $unpack_data = unpack('Ntotal_length', $buffer);
36 | return $unpack_data['total_length'];
37 | }
38 |
39 | /**
40 | * Decode.
41 | *
42 | * @param string $buffer
43 | * @return string
44 | */
45 | public static function decode($buffer)
46 | {
47 | return substr($buffer, 4);
48 | }
49 |
50 | /**
51 | * Encode.
52 | *
53 | * @param string $buffer
54 | * @return string
55 | */
56 | public static function encode($buffer)
57 | {
58 | $total_length = 4 + strlen($buffer);
59 | return pack('N', $total_length) . $buffer;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Protocols/Game.php:
--------------------------------------------------------------------------------
1 |
11 | * @copyright walkor
12 | * @link http://www.workerman.net/
13 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
14 | */
15 | namespace Workerman\Protocols;
16 |
17 | use Workerman\Connection\TcpConnection;
18 |
19 | /**
20 | * Frame Protocol.
21 | */
22 | class Game {
23 | /**
24 | * 检查包的完整性
25 | * 如果能够得到包长,则返回包的在buffer中的长度,否则返回0继续等待数据
26 | * 如果协议有问题,则可以返回false,当前客户端连接会因此断开
27 | *
28 | * @param string $buffer
29 | * @return int
30 | */
31 | public static function input($buffer, TcpConnection $connection) {
32 | if (strlen ( $buffer ) < 2) {
33 | return 0;
34 | }
35 | // unpack() 函数从二进制字符串对数据进行解包。
36 | $unpack_data = unpack ( 'Stotal_length', $buffer );
37 | return ( int ) $unpack_data ['total_length'] + 2;
38 | }
39 |
40 | /**
41 | * 解包,当接收到的数据字节数等于input返回的值(大于0的值)自动调用
42 | * 并传递给onMessage回调函数的$data参数
43 | *
44 | * @param string $buffer
45 | * @return string
46 | */
47 | public static function decode($buffer) {
48 | $buffer = substr ( $buffer, 2 );
49 | return $buffer;
50 | }
51 |
52 | /**
53 | * 打包,当向客户端发送数据的时候会自动调用
54 | *
55 | * @param string $buffer
56 | * @return string
57 | */
58 | public static function encode($buffer) {
59 | $bin_body = pack ( "a*", $buffer . "\0" );
60 | $body_len = strlen ( $bin_body );
61 | $bin_head = pack ( 'S*', $body_len );
62 |
63 | $bin = $bin_head . $bin_body;
64 |
65 | return $bin;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Protocols/Game.php:
--------------------------------------------------------------------------------
1 |
11 | * @copyright walkor
12 | * @link http://www.workerman.net/
13 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
14 | */
15 | namespace Workerman\Protocols;
16 |
17 | use Workerman\Connection\TcpConnection;
18 |
19 | /**
20 | * Frame Protocol.
21 | */
22 | class Game {
23 | /**
24 | * 检查包的完整性
25 | * 如果能够得到包长,则返回包的在buffer中的长度,否则返回0继续等待数据
26 | * 如果协议有问题,则可以返回false,当前客户端连接会因此断开
27 | *
28 | * @param string $buffer
29 | * @return int
30 | */
31 | public static function input($buffer, TcpConnection $connection) {
32 | if (strlen ( $buffer ) < 2) {
33 | return 0;
34 | }
35 | // unpack() 函数从二进制字符串对数据进行解包。
36 | $unpack_data = unpack ( 'Stotal_length', $buffer );
37 | return ( int ) $unpack_data ['total_length'] + 2;
38 | }
39 |
40 | /**
41 | * 解包,当接收到的数据字节数等于input返回的值(大于0的值)自动调用
42 | * 并传递给onMessage回调函数的$data参数
43 | *
44 | * @param string $buffer
45 | * @return string
46 | */
47 | public static function decode($buffer) {
48 | $buffer = substr ( $buffer, 2 );
49 | return $buffer;
50 | }
51 |
52 | /**
53 | * 打包,当向客户端发送数据的时候会自动调用
54 | *
55 | * @param string $buffer
56 | * @return string
57 | */
58 | public static function encode($buffer) {
59 | $bin_body = pack ( "a*", $buffer . "\0" );
60 | $body_len = strlen ( $bin_body );
61 | $bin_head = pack ( 'S*', $body_len );
62 |
63 | $bin = $bin_head . $bin_body;
64 |
65 | return $bin;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/start_app.php:
--------------------------------------------------------------------------------
1 | name = APE["config"] ["worker_name"];
23 | $apeWeb->max_request = APE["config"] ["max_request"];
24 | $apeWeb->count = APE["config"] ["worker_count"];
25 |
26 | $apeWeb->onStart = function ($apeWeb) {
27 | // 创建数据库连接
28 | $config = APE["config"];
29 | $database = APE["database"];
30 |
31 | $mysqls = array();
32 | foreach ($database as $k => $n) {
33 | $mysqls[$k] = new MySQL($n ['host'], $n ['port'], $n ['username'], $n ['password'], $n ['db_name']);
34 | }
35 | ApeWeb::$mysqls = $mysqls;
36 | ApeWeb::$view = new View();
37 |
38 | // 删除所有垃圾视图,重新生成、
39 | if ($apeWeb->id==0) {
40 | foreach (glob(RUN_DIR . 'z_*/storage/views/*.php') as $start_file) {
41 | unlink($start_file);
42 | }
43 | }
44 |
45 | require_once RUN_DIR."config/filter.php";
46 | foreach (glob(RUN_DIR . 'z_*/filter.php') as $file) {
47 | require_once($file);
48 | }
49 |
50 | //链接UDP日志服务器 start
51 | ApeWeb::$udp_log_client = new AsyncTcpConnection("udp://127.0.0.1:".APE['config']['port']);
52 | ApeWeb::$udp_log_client->connect();
53 | //链接UDP日志服务器 end
54 | };
55 |
56 | if(APE["WORKERMAN"] == "Workerman_win"){
57 | Worker::runAll();
58 | }
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Protocols/ProtocolInterface.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Protocols;
15 |
16 | use Workerman\Connection\ConnectionInterface;
17 |
18 | /**
19 | * Protocol interface
20 | */
21 | interface ProtocolInterface
22 | {
23 | /**
24 | * Check the integrity of the package.
25 | * Please return the length of package.
26 | * If length is unknow please return 0 that mean wating more data.
27 | * If the package has something wrong please return false the connection will be closed.
28 | *
29 | * @param ConnectionInterface $connection
30 | * @param string $recv_buffer
31 | * @return int|false
32 | */
33 | public static function input($recv_buffer, ConnectionInterface $connection);
34 |
35 | /**
36 | * Decode package and emit onMessage($message) callback, $message is the result that decode returned.
37 | *
38 | * @param ConnectionInterface $connection
39 | * @param string $recv_buffer
40 | * @return mixed
41 | */
42 | public static function decode($recv_buffer, ConnectionInterface $connection);
43 |
44 | /**
45 | * Encode package brefore sending to client.
46 | *
47 | * @param ConnectionInterface $connection
48 | * @param mixed $data
49 | * @return string
50 | */
51 | public static function encode($data, ConnectionInterface $connection);
52 | }
53 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Protocols/ProtocolInterface.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Protocols;
15 |
16 | use Workerman\Connection\ConnectionInterface;
17 |
18 | /**
19 | * Protocol interface
20 | */
21 | interface ProtocolInterface
22 | {
23 | /**
24 | * Check the integrity of the package.
25 | * Please return the length of package.
26 | * If length is unknow please return 0 that mean wating more data.
27 | * If the package has something wrong please return false the connection will be closed.
28 | *
29 | * @param ConnectionInterface $connection
30 | * @param string $recv_buffer
31 | * @return int|false
32 | */
33 | public static function input($recv_buffer, ConnectionInterface $connection);
34 |
35 | /**
36 | * Decode package and emit onMessage($message) callback, $message is the result that decode returned.
37 | *
38 | * @param ConnectionInterface $connection
39 | * @param string $recv_buffer
40 | * @return mixed
41 | */
42 | public static function decode($recv_buffer, ConnectionInterface $connection);
43 |
44 | /**
45 | * Encode package brefore sending to client.
46 | *
47 | * @param ConnectionInterface $connection
48 | * @param mixed $data
49 | * @return string
50 | */
51 | public static function encode($data, ConnectionInterface $connection);
52 | }
53 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Autoloader.php:
--------------------------------------------------------------------------------
1 |
11 | * @copyright walkor
12 | * @link http://www.workerman.net/
13 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
14 | */
15 | namespace Workerman;
16 |
17 | // 包含常量定义文件
18 | require_once __DIR__ . '/Lib/Constants.php';
19 |
20 | /**
21 | * 自动加载类
22 | *
23 | * @author walkor
24 | */
25 | class Autoloader {
26 |
27 | // 项目目录,默认是根目录
28 | protected static $_appInitPath= '';
29 | // lib文件目录,如果用namespace在外面没找到,尝试在lib下寻找
30 | protected static $_libPath = '_lib';
31 |
32 | /**
33 | * 设置应用初始化目录
34 | *
35 | * @param string $root_path
36 | * @return void
37 | */
38 | public static function setRootPath($root_path) {
39 | self::$_appInitPath = $root_path;
40 | }
41 |
42 | /**
43 | * 根据命名空间加载文件
44 | *
45 | * @param string $name
46 | * @return boolean
47 | */
48 | public static function loadByNamespace($name) {
49 | // 相对路径
50 | $class_path = str_replace ( '\\', DIRECTORY_SEPARATOR, $name );
51 |
52 | // 先尝试通过namespace 匹配地址寻找
53 | $class_file = $class_path . '.php';
54 |
55 | //如果没找到的话,再在_lib文件夹下寻找
56 | if (!is_file ( $class_file )) {
57 | $class_file = self::$_libPath. DIRECTORY_SEPARATOR . $class_path . '.php';
58 | //echo "$class_file"."\n";
59 | }
60 | // 找到文件
61 | if (is_file ( $class_file )) {
62 | // 加载
63 | require_once ($class_file);
64 | if (class_exists ( $name, false )) {
65 | return true;
66 | }
67 | }
68 | return false;
69 | }
70 | }
71 |
72 | // 设置类自动加载回调函数
73 | spl_autoload_register ( '\Workerman\Autoloader::loadByNamespace' );
74 |
--------------------------------------------------------------------------------
/start_filemonitor.php:
--------------------------------------------------------------------------------
1 | name = 'FileMonitor';
24 | $worker->reloadable = false;
25 | $last_mtime = time ();
26 |
27 | $worker->onWorkerStart = function () {
28 | global $monitor_dir;
29 | // watch files only in daemon mode
30 | if (! Worker::$daemonize) {
31 | // chek mtime of files per second
32 | Timer::add ( 1, 'check_files_change', array (
33 | $monitor_dir
34 | ) );
35 | }
36 | };
37 |
38 | // check files func
39 | function check_files_change($monitor_dir) {
40 | global $last_time_arr;
41 | // recursive traversal directory
42 | $dir_iterator = new RecursiveDirectoryIterator ( $monitor_dir );
43 | $iterator = new RecursiveIteratorIterator ( $dir_iterator );
44 | foreach ( $iterator as $file ) {
45 | // only check php files
46 | if (pathinfo ( $file, PATHINFO_EXTENSION ) != 'php') {
47 | continue;
48 | }
49 | if(!array_key_exists((string)$file,$last_time_arr)){
50 | $last_time_arr[(string)$file] = $file->getMTime ();
51 | }
52 | if ($last_time_arr[(string)$file] < $file->getMTime ()) {
53 | echo $file . " update and reload\n";
54 | // send SIGUSR1 signal to master process for reload
55 | posix_kill ( posix_getppid (), SIGUSR1 );
56 | $last_time_arr[(string)$file] = $file->getMTime ();
57 | break;
58 | }
59 | }
60 | }
61 |
62 | if(APE["WORKERMAN"] == "Workerman_win"){
63 | Worker::runAll();
64 | }
65 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Protocols/Text.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Protocols;
15 |
16 | use Workerman\Connection\TcpConnection;
17 |
18 | /**
19 | * Text Protocol.
20 | */
21 | class Text
22 | {
23 | /**
24 | * Check the integrity of the package.
25 | *
26 | * @param string $buffer
27 | * @param TcpConnection $connection
28 | * @return int
29 | */
30 | public static function input($buffer, TcpConnection $connection)
31 | {
32 | // Judge whether the package length exceeds the limit.
33 | if (strlen($buffer) >= TcpConnection::$maxPackageSize) {
34 | $connection->close();
35 | return 0;
36 | }
37 | // Find the position of "\n".
38 | $pos = strpos($buffer, "\n");
39 | // No "\n", packet length is unknown, continue to wait for the data so return 0.
40 | if ($pos === false) {
41 | return 0;
42 | }
43 | // Return the current package length.
44 | return $pos + 1;
45 | }
46 |
47 | /**
48 | * Encode.
49 | *
50 | * @param string $buffer
51 | * @return string
52 | */
53 | public static function encode($buffer)
54 | {
55 | // Add "\n"
56 | return $buffer . "\n";
57 | }
58 |
59 | /**
60 | * Decode.
61 | *
62 | * @param string $buffer
63 | * @return string
64 | */
65 | public static function decode($buffer)
66 | {
67 | // Remove "\n"
68 | return trim($buffer);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Protocols/Text.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Protocols;
15 |
16 | use Workerman\Connection\TcpConnection;
17 |
18 | /**
19 | * Text Protocol.
20 | */
21 | class Text
22 | {
23 | /**
24 | * Check the integrity of the package.
25 | *
26 | * @param string $buffer
27 | * @param TcpConnection $connection
28 | * @return int
29 | */
30 | public static function input($buffer, TcpConnection $connection)
31 | {
32 | // Judge whether the package length exceeds the limit.
33 | if (strlen($buffer) >= TcpConnection::$maxPackageSize) {
34 | $connection->close();
35 | return 0;
36 | }
37 | // Find the position of "\n".
38 | $pos = strpos($buffer, "\n");
39 | // No "\n", packet length is unknown, continue to wait for the data so return 0.
40 | if ($pos === false) {
41 | return 0;
42 | }
43 | // Return the current package length.
44 | return $pos + 1;
45 | }
46 |
47 | /**
48 | * Encode.
49 | *
50 | * @param string $buffer
51 | * @return string
52 | */
53 | public static function encode($buffer)
54 | {
55 | // Add "\n"
56 | return $buffer . "\n";
57 | }
58 |
59 | /**
60 | * Decode.
61 | *
62 | * @param string $buffer
63 | * @return string
64 | */
65 | public static function decode($buffer)
66 | {
67 | // Remove "\n"
68 | return trim($buffer);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Events/EventInterface.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events;
15 |
16 | interface EventInterface
17 | {
18 | /**
19 | * Read event.
20 | *
21 | * @var int
22 | */
23 | const EV_READ = 1;
24 |
25 | /**
26 | * Write event.
27 | *
28 | * @var int
29 | */
30 | const EV_WRITE = 2;
31 |
32 | /**
33 | * Except event
34 | *
35 | * @var int
36 | */
37 | const EV_EXCEPT = 3;
38 |
39 | /**
40 | * Signal event.
41 | *
42 | * @var int
43 | */
44 | const EV_SIGNAL = 4;
45 |
46 | /**
47 | * Timer event.
48 | *
49 | * @var int
50 | */
51 | const EV_TIMER = 8;
52 |
53 | /**
54 | * Timer once event.
55 | *
56 | * @var int
57 | */
58 | const EV_TIMER_ONCE = 16;
59 |
60 | /**
61 | * Add event listener to event loop.
62 | *
63 | * @param mixed $fd
64 | * @param int $flag
65 | * @param callable $func
66 | * @param mixed $args
67 | * @return bool
68 | */
69 | public function add($fd, $flag, $func, $args = null);
70 |
71 | /**
72 | * Remove event listener from event loop.
73 | *
74 | * @param mixed $fd
75 | * @param int $flag
76 | * @return bool
77 | */
78 | public function del($fd, $flag);
79 |
80 | /**
81 | * Remove all timers.
82 | *
83 | * @return void
84 | */
85 | public function clearAllTimer();
86 |
87 | /**
88 | * Main loop.
89 | *
90 | * @return void
91 | */
92 | public function loop();
93 | }
94 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Events/EventInterface.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events;
15 |
16 | interface EventInterface
17 | {
18 | /**
19 | * Read event.
20 | *
21 | * @var int
22 | */
23 | const EV_READ = 1;
24 |
25 | /**
26 | * Write event.
27 | *
28 | * @var int
29 | */
30 | const EV_WRITE = 2;
31 |
32 | /**
33 | * Signal event.
34 | *
35 | * @var int
36 | */
37 | const EV_SIGNAL = 4;
38 |
39 | /**
40 | * Timer event.
41 | *
42 | * @var int
43 | */
44 | const EV_TIMER = 8;
45 |
46 | /**
47 | * Timer once event.
48 | *
49 | * @var int
50 | */
51 | const EV_TIMER_ONCE = 16;
52 |
53 | /**
54 | * Add event listener to event loop.
55 | *
56 | * @param mixed $fd
57 | * @param int $flag
58 | * @param callable $func
59 | * @param mixed $args
60 | * @return bool
61 | */
62 | public function add($fd, $flag, $func, $args = null);
63 |
64 | /**
65 | * Remove event listener from event loop.
66 | *
67 | * @param mixed $fd
68 | * @param int $flag
69 | * @return bool
70 | */
71 | public function del($fd, $flag);
72 |
73 | /**
74 | * Remove all timers.
75 | *
76 | * @return void
77 | */
78 | public function clearAllTimer();
79 |
80 | /**
81 | * Main loop.
82 | *
83 | * @return void
84 | */
85 | public function loop();
86 |
87 | /**
88 | * Destroy loop.
89 | *
90 | * @return mixed
91 | */
92 | public function destroy();
93 | }
94 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Connection/ConnectionInterface.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Connection;
15 |
16 | /**
17 | * ConnectionInterface.
18 | */
19 | abstract class ConnectionInterface
20 | {
21 | /**
22 | * Statistics for status command.
23 | *
24 | * @var array
25 | */
26 | public static $statistics = array(
27 | 'connection_count' => 0,
28 | 'total_request' => 0,
29 | 'throw_exception' => 0,
30 | 'send_fail' => 0,
31 | );
32 |
33 | /**
34 | * Emitted when data is received.
35 | *
36 | * @var callback
37 | */
38 | public $onMessage = null;
39 |
40 | /**
41 | * Emitted when the other end of the socket sends a FIN packet.
42 | *
43 | * @var callback
44 | */
45 | public $onClose = null;
46 |
47 | /**
48 | * Emitted when an error occurs with connection.
49 | *
50 | * @var callback
51 | */
52 | public $onError = null;
53 |
54 | /**
55 | * Sends data on the connection.
56 | *
57 | * @param string $send_buffer
58 | * @return void|boolean
59 | */
60 | abstract public function send($send_buffer);
61 |
62 | /**
63 | * Get remote IP.
64 | *
65 | * @return string
66 | */
67 | abstract public function getRemoteIp();
68 |
69 | /**
70 | * Get remote port.
71 | *
72 | * @return int
73 | */
74 | abstract public function getRemotePort();
75 |
76 | /**
77 | * Close connection.
78 | *
79 | * @param $data
80 | * @return void
81 | */
82 | abstract public function close($data = null);
83 | }
84 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Connection/ConnectionInterface.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Connection;
15 |
16 | /**
17 | * ConnectionInterface.
18 | */
19 | abstract class ConnectionInterface
20 | {
21 | /**
22 | * Statistics for status command.
23 | *
24 | * @var array
25 | */
26 | public static $statistics = array(
27 | 'connection_count' => 0,
28 | 'total_request' => 0,
29 | 'throw_exception' => 0,
30 | 'send_fail' => 0,
31 | );
32 |
33 | /**
34 | * Emitted when data is received.
35 | *
36 | * @var callback
37 | */
38 | public $onMessage = null;
39 |
40 | /**
41 | * Emitted when the other end of the socket sends a FIN packet.
42 | *
43 | * @var callback
44 | */
45 | public $onClose = null;
46 |
47 | /**
48 | * Emitted when an error occurs with connection.
49 | *
50 | * @var callback
51 | */
52 | public $onError = null;
53 |
54 | /**
55 | * Sends data on the connection.
56 | *
57 | * @param string $send_buffer
58 | * @return void|boolean
59 | */
60 | abstract public function send($send_buffer);
61 |
62 | /**
63 | * Get remote IP.
64 | *
65 | * @return string
66 | */
67 | abstract public function getRemoteIp();
68 |
69 | /**
70 | * Get remote port.
71 | *
72 | * @return int
73 | */
74 | abstract public function getRemotePort();
75 |
76 | /**
77 | * Close connection.
78 | *
79 | * @param $data
80 | * @return void
81 | */
82 | abstract public function close($data = null);
83 | }
84 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Autoloader.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman;
15 |
16 | /**
17 | * Autoload.
18 | */
19 | class Autoloader
20 | {
21 | /**
22 | * Autoload root path.
23 | *
24 | * @var string
25 | */
26 | protected static $_autoloadRootPath = '';
27 |
28 | /**
29 | * Set autoload root path.
30 | *
31 | * @param string $root_path
32 | * @return void
33 | */
34 | public static function setRootPath($root_path)
35 | {
36 | self::$_autoloadRootPath = $root_path;
37 | }
38 |
39 | /**
40 | * Load files by namespace.
41 | *
42 | * @param string $name
43 | * @return boolean
44 | */
45 | public static function loadByNamespace($name)
46 | {
47 | $class_path = str_replace('\\', DIRECTORY_SEPARATOR, $name);
48 | if (strpos($name, 'Workerman\\') === 0) {
49 | $class_file = __DIR__ . substr($class_path, strlen('Workerman')) . '.php';
50 | } else {
51 | if (self::$_autoloadRootPath) {
52 | $class_file = self::$_autoloadRootPath . DIRECTORY_SEPARATOR . $class_path . '.php';
53 | }
54 | if (empty($class_file) || !is_file($class_file)) {
55 | $class_file = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . "$class_path.php";
56 | }
57 | }
58 |
59 | if (is_file($class_file)) {
60 | require_once($class_file);
61 | if (class_exists($name, false)) {
62 | return true;
63 | }
64 | }
65 | return false;
66 | }
67 | }
68 |
69 | spl_autoload_register('\Workerman\Autoloader::loadByNamespace');
--------------------------------------------------------------------------------
/_lib/Workerman_win/Events/React/ExtEventLoop.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events\React;
15 |
16 | /**
17 | * Class ExtEventLoop
18 | * @package Workerman\Events\React
19 | */
20 | class ExtEventLoop extends \React\EventLoop\ExtEventLoop
21 | {
22 | /**
23 | * Event base.
24 | *
25 | * @var EventBase
26 | */
27 | protected $_eventBase = null;
28 |
29 | /**
30 | * All signal Event instances.
31 | *
32 | * @var array
33 | */
34 | protected $_signalEvents = array();
35 |
36 | /**
37 | * Construct
38 | */
39 | public function __construct()
40 | {
41 | parent::__construct();
42 | $class = new \ReflectionClass('\React\EventLoop\ExtEventLoop');
43 | $property = $class->getProperty('eventBase');
44 | $property->setAccessible(true);
45 | $this->_eventBase = $property->getValue($this);
46 | }
47 |
48 | /**
49 | * Add signal handler.
50 | *
51 | * @param $signal
52 | * @param $callback
53 | * @return bool
54 | */
55 | public function addSignal($signal, $callback)
56 | {
57 | $event = \Event::signal($this->_eventBase, $signal, $callback);
58 | if (!$event||!$event->add()) {
59 | return false;
60 | }
61 | $this->_signalEvents[$signal] = $event;
62 | }
63 |
64 | /**
65 | * Remove signal handler.
66 | *
67 | * @param $signal
68 | */
69 | public function removeSignal($signal)
70 | {
71 | if (isset($this->_signalEvents[$signal])) {
72 | $this->_signalEvents[$signal]->del();
73 | unset($this->_signalEvents[$signal]);
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Events/React/LibEventLoop.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events\React;
15 |
16 | /**
17 | * Class LibEventLoop
18 | * @package Workerman\Events\React
19 | */
20 | class LibEventLoop extends \React\EventLoop\LibEventLoop
21 | {
22 | /**
23 | * Event base.
24 | *
25 | * @var event_base resource
26 | */
27 | protected $_eventBase = null;
28 |
29 | /**
30 | * All signal Event instances.
31 | *
32 | * @var array
33 | */
34 | protected $_signalEvents = array();
35 |
36 | /**
37 | * Construct.
38 | */
39 | public function __construct()
40 | {
41 | parent::__construct();
42 | $class = new \ReflectionClass('\React\EventLoop\LibEventLoop');
43 | $property = $class->getProperty('eventBase');
44 | $property->setAccessible(true);
45 | $this->_eventBase = $property->getValue($this);
46 | }
47 |
48 | /**
49 | * Add signal handler.
50 | *
51 | * @param $signal
52 | * @param $callback
53 | * @return bool
54 | */
55 | public function addSignal($signal, $callback)
56 | {
57 | $event = event_new();
58 | $this->_signalEvents[$signal] = $event;
59 | event_set($event, $signal, EV_SIGNAL | EV_PERSIST, $callback);
60 | event_base_set($event, $this->_eventBase);
61 | event_add($event);
62 | }
63 |
64 | /**
65 | * Remove signal handler.
66 | *
67 | * @param $signal
68 | */
69 | public function removeSignal($signal)
70 | {
71 | if (isset($this->_signalEvents[$signal])) {
72 | $event = $this->_signalEvents[$signal];
73 | event_del($event);
74 | unset($this->_signalEvents[$signal]);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/_lib/ape/register.php:
--------------------------------------------------------------------------------
1 | count = 1;
10 | $worker->name = 'ape_register';
11 |
12 | Worker::$logFile = __DIR__ . "/register_log.log";
13 | Worker::$stdoutFile = __DIR__ . "/register_stdout.log";
14 |
15 | // 保存所有客户端
16 | $clients = array();
17 | $worker->onMessage = function ($connection, $buffer) {
18 | global $clients;
19 | // 客户端进行注册
20 | if (strpos($buffer, "register_") === 0) {
21 | $listen_address = str_replace("register_", "", $buffer);
22 | $listen_address = str_replace("0.0.0.0", "127.0.0.1", $listen_address);
23 | if (! array_key_exists($listen_address, $clients)) {
24 | if ($listen_address == "") {
25 | $connection->close();
26 | return;
27 | }
28 | $clients [$listen_address] = true;
29 | var_dump($listen_address . " is reg~~~~~~~~ ");
30 | }
31 | $connection->close();
32 | return;
33 | }
34 | if (count($clients) > 0) {
35 | global $_key;
36 | $_key = key($clients);
37 | if ($_key == false) {
38 | reset($clients);
39 | $_key = key($clients);
40 | }
41 | $remote_connection = new AsyncTcpConnection("tcp://" . $_key);
42 | next($clients);
43 | $remote_connection->onError = function ($remote_connection) use ($connection) {
44 | global $clients;
45 | global $_key;
46 | var_dump($_key . " is close!!!!!!!!! ");
47 | unset($clients [$_key]);
48 | $connection->send("HTTP/1.1 502 Connection Established\r\n\r\n");
49 | $connection->close();
50 | return;
51 | };
52 | $remote_connection->send($buffer);
53 | // Pipe.
54 | $remote_connection->pipe($connection);
55 | $connection->pipe($remote_connection);
56 | $remote_connection->connect();
57 | } else {
58 | $connection->send("HTTP/1.1 502 Connection Established\r\n\r\n");
59 | $connection->close();
60 | }
61 | };
62 |
63 | // Run.
64 | Worker::runAll();
65 |
--------------------------------------------------------------------------------
/_lib/ape/base/MYSQL:
--------------------------------------------------------------------------------
1 | // 初始化db连接
2 | $db = new Workerman\MySQL\Connection('host', 'port', 'user', 'password', 'db_name');
3 |
4 | // 获取所有数据
5 | $db->select('ID,Sex')->from('Persons')->where('sex= :sex')->bindValues(array('sex'=>'M'))->query();
6 | //等价于
7 | $db->select('ID,Sex')->from('Persons')->where("sex= 'F' ")->query();
8 | //等价于
9 | $db->query("SELECT ID,Sex FROM `Persons` WHERE sex='M'");
10 |
11 |
12 | // 获取一行数据
13 | $db->select('ID,Sex')->from('Persons')->where('sex= :sex')->bindValues(array('sex'=>'M'))->row();
14 | //等价于
15 | $db->select('ID,Sex')->from('Persons')->where("sex= 'F' ")->row();
16 | //等价于
17 | $db->row("SELECT ID,Sex FROM `Persons` WHERE sex='M'");
18 |
19 |
20 | // 获取一列数据
21 | $db->select('ID')->from('Persons')->where('sex= :sex')->bindValues(array('sex'=>'M'))->column();
22 | //等价于
23 | $db->select('ID')->from('Persons')->where("sex= 'F' ")->column();
24 | //等价于
25 | $db->column("SELECT `ID` FROM `Persons` WHERE sex='M'");
26 |
27 | // 获取单个值
28 | $db->select('ID,Sex')->from('Persons')->where('sex= :sex')->bindValues(array('sex'=>'M'))->single();
29 | //等价于
30 | $db->select('ID,Sex')->from('Persons')->where("sex= 'F' ")->single();
31 | //等价于
32 | $db->single("SELECT ID,Sex FROM `Persons` WHERE sex='M'");
33 |
34 | // 复杂查询
35 | $db->select('*')->from('table1')->innerJoin('table2','table1.uid = table2.uid')->where('age > :age')->groupBy(array('aid'))->having('foo="foo"')->orderByASC/*orderByDESC*/(array('did'))
36 | ->limit(10)->offset(20)->bindValues(array('age' => 13));
37 | // 等价于
38 | $db->query(SELECT * FROM `table1` INNER JOIN `table2` ON `table1`.`uid` = `table2`.`uid`
39 | WHERE age > 13 GROUP BY aid HAVING foo="foo" ORDER BY did LIMIT 10 OFFSET 20“);
40 |
41 | // 插入
42 | $insert_id = $db->insert('Persons')->cols(array(
43 | 'Firstname'=>'abc',
44 | 'Lastname'=>'efg',
45 | 'Sex'=>'M',
46 | 'Age'=>13))->query();
47 | 等价于
48 | $insert_id = $db->query("INSERT INTO `Persons` ( `Firstname`,`Lastname`,`Sex`,`Age`)
49 | VALUES ( 'abc', 'efg', 'M', 13)");
50 |
51 | // 更新
52 | $row_count = $db->update('Persons')->cols(array('sex'))->where('ID=1')
53 | ->bindValue('sex', 'F')->query();
54 | // 等价于
55 | $row_count = $db->update('Persons')->cols(array('sex'=>'F'))->where('ID=1')->query();
56 | // 等价于
57 | $row_count = $db->query("UPDATE `Persons` SET `sex` = 'F' WHERE ID=1");
58 |
59 | // 删除
60 | $row_count = $db->delete('Persons')->where('ID=9')->query();
61 | // 等价于
62 | $row_count = $db->query("DELETE FROM `Persons` WHERE ID=9");
63 |
64 | // 事务
65 | $db->beginTrans();
66 | ....
67 | $db->commitTrans(); // or $db->rollBackTrans();
--------------------------------------------------------------------------------
/_lib/Workerman_win/Events/React/StreamSelectLoop.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events\React;
15 |
16 | /**
17 | * Class StreamSelectLoop
18 | * @package Workerman\Events\React
19 | */
20 | class StreamSelectLoop extends \React\EventLoop\StreamSelectLoop
21 | {
22 | /**
23 | * Add signal handler.
24 | *
25 | * @param $signal
26 | * @param $callback
27 | * @return bool
28 | */
29 | public function addSignal($signal, $callback)
30 | {
31 | if(PHP_EOL !== "\r\n") {
32 | pcntl_signal($signal, $callback);
33 | }
34 | }
35 |
36 | /**
37 | * Remove signal handler.
38 | *
39 | * @param $signal
40 | */
41 | public function removeSignal($signal)
42 | {
43 | if(PHP_EOL !== "\r\n") {
44 | pcntl_signal($signal, SIG_IGN);
45 | }
46 | }
47 |
48 | /**
49 | * Emulate a stream_select() implementation that does not break when passed
50 | * empty stream arrays.
51 | *
52 | * @param array &$read An array of read streams to select upon.
53 | * @param array &$write An array of write streams to select upon.
54 | * @param integer|null $timeout Activity timeout in microseconds, or null to wait forever.
55 | *
56 | * @return integer|false The total number of streams that are ready for read/write.
57 | * Can return false if stream_select() is interrupted by a signal.
58 | */
59 | protected function streamSelect(array &$read, array &$write, $timeout)
60 | {
61 | if ($read || $write) {
62 | $except = null;
63 | // Calls signal handlers for pending signals
64 | pcntl_signal_dispatch();
65 | // suppress warnings that occur, when stream_select is interrupted by a signal
66 | return @stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout);
67 | }
68 |
69 | // Calls signal handlers for pending signals
70 | if(PHP_EOL !== "\r\n") {
71 | pcntl_signal_dispatch();
72 | }
73 | $timeout && usleep($timeout);
74 |
75 | return 0;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/_lib/GlobalData/Server.php:
--------------------------------------------------------------------------------
1 | count = 1;
34 | $worker->name = 'globalDataServer';
35 | $worker->onMessage = array (
36 | $this,
37 | 'onMessage'
38 | );
39 | $worker->reloadable = false;
40 | $this->_worker = $worker;
41 | }
42 |
43 | /**
44 | * onMessage.
45 | *
46 | * @param TcpConnection $connection
47 | * @param string $buffer
48 | */
49 | public function onMessage($connection, $buffer) {
50 | if ($buffer === 'ping') {
51 | return;
52 | }
53 | $data = unserialize ( $buffer );
54 | if (! $buffer || ! isset ( $data ['cmd'] ) || ! isset ( $data ['key'] )) {
55 | return $connection->close ( serialize ( 'bad request' ) );
56 | }
57 | $cmd = $data ['cmd'];
58 | $key = $data ['key'];
59 | switch ($cmd) {
60 | case 'get' :
61 | if (! isset ( $this->_dataArray [$key] )) {
62 | return $connection->send ( 'N;' );
63 | }
64 | return $connection->send ( serialize ( $this->_dataArray [$key] ) );
65 | break;
66 | case 'set' :
67 | $this->_dataArray [$key] = $data ['value'];
68 | $connection->send ( 'b:1;' );
69 | break;
70 | case 'add' :
71 | if (isset ( $this->_dataArray [$key] )) {
72 | return $connection->send ( 'b:0;' );
73 | }
74 | $this->_dataArray [$key] = $data ['value'];
75 | return $connection->send ( 'b:1;' );
76 | break;
77 | case 'increment' :
78 | if (! isset ( $this->_dataArray [$key] )) {
79 | return $connection->send ( 'b:0;' );
80 | }
81 | if (! is_numeric ( $this->_dataArray [$key] )) {
82 | $this->_dataArray [$key] = 0;
83 | }
84 | $this->_dataArray [$key] = $this->_dataArray [$key] + $data ['step'];
85 | return $connection->send ( serialize ( $this->_dataArray [$key] ) );
86 | break;
87 | case 'cas' :
88 | if (isset ( $this->_dataArray [$key] ) && md5 ( serialize ( $this->_dataArray [$key] ) ) === $data ['md5']) {
89 | $this->_dataArray [$key] = $data ['value'];
90 | return $connection->send ( 'b:1;' );
91 | }
92 | $connection->send ( 'b:0;' );
93 | break;
94 | case 'delete' :
95 | unset ( $this->_dataArray [$key] );
96 | $connection->send ( 'b:1;' );
97 | break;
98 | default :
99 | $connection->close ( serialize ( 'bad cmd ' . $cmd ) );
100 | }
101 | }
102 | }
103 |
104 |
105 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Connection/UdpConnection.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Connection;
15 |
16 | /**
17 | * UdpConnection.
18 | */
19 | class UdpConnection extends ConnectionInterface
20 | {
21 | /**
22 | * Application layer protocol.
23 | * The format is like this Workerman\\Protocols\\Http.
24 | *
25 | * @var \Workerman\Protocols\ProtocolInterface
26 | */
27 | public $protocol = null;
28 |
29 | /**
30 | * Udp socket.
31 | *
32 | * @var resource
33 | */
34 | protected $_socket = null;
35 |
36 | /**
37 | * Remote address.
38 | *
39 | * @var string
40 | */
41 | protected $_remoteAddress = '';
42 |
43 | /**
44 | * Construct.
45 | *
46 | * @param resource $socket
47 | * @param string $remote_address
48 | */
49 | public function __construct($socket, $remote_address)
50 | {
51 | $this->_socket = $socket;
52 | $this->_remoteAddress = $remote_address;
53 | }
54 |
55 | /**
56 | * Sends data on the connection.
57 | *
58 | * @param string $send_buffer
59 | * @param bool $raw
60 | * @return void|boolean
61 | */
62 | public function send($send_buffer, $raw = false)
63 | {
64 | if (false === $raw && $this->protocol) {
65 | $parser = $this->protocol;
66 | $send_buffer = $parser::encode($send_buffer, $this);
67 | if ($send_buffer === '') {
68 | return null;
69 | }
70 | }
71 | return strlen($send_buffer) === stream_socket_sendto($this->_socket, $send_buffer, 0, $this->_remoteAddress);
72 | }
73 |
74 | /**
75 | * Get remote IP.
76 | *
77 | * @return string
78 | */
79 | public function getRemoteIp()
80 | {
81 | $pos = strrpos($this->_remoteAddress, ':');
82 | if ($pos) {
83 | return trim(substr($this->_remoteAddress, 0, $pos), '[]');
84 | }
85 | return '';
86 | }
87 |
88 | /**
89 | * Get remote port.
90 | *
91 | * @return int
92 | */
93 | public function getRemotePort()
94 | {
95 | if ($this->_remoteAddress) {
96 | return (int)substr(strrchr($this->_remoteAddress, ':'), 1);
97 | }
98 | return 0;
99 | }
100 |
101 | /**
102 | * Close connection.
103 | *
104 | * @param mixed $data
105 | * @param bool $raw
106 | * @return bool
107 | */
108 | public function close($data = null, $raw = false)
109 | {
110 | if ($data !== null) {
111 | $this->send($data, $raw);
112 | }
113 | return true;
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Connection/UdpConnection.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Connection;
15 |
16 | /**
17 | * UdpConnection.
18 | */
19 | class UdpConnection extends ConnectionInterface
20 | {
21 | /**
22 | * Application layer protocol.
23 | * The format is like this Workerman\\Protocols\\Http.
24 | *
25 | * @var \Workerman\Protocols\ProtocolInterface
26 | */
27 | public $protocol = null;
28 |
29 | /**
30 | * Udp socket.
31 | *
32 | * @var resource
33 | */
34 | protected $_socket = null;
35 |
36 | /**
37 | * Remote address.
38 | *
39 | * @var string
40 | */
41 | protected $_remoteAddress = '';
42 |
43 | /**
44 | * Construct.
45 | *
46 | * @param resource $socket
47 | * @param string $remote_address
48 | */
49 | public function __construct($socket, $remote_address)
50 | {
51 | $this->_socket = $socket;
52 | $this->_remoteAddress = $remote_address;
53 | }
54 |
55 | /**
56 | * Sends data on the connection.
57 | *
58 | * @param string $send_buffer
59 | * @param bool $raw
60 | * @return void|boolean
61 | */
62 | public function send($send_buffer, $raw = false)
63 | {
64 | if (false === $raw && $this->protocol) {
65 | $parser = $this->protocol;
66 | $send_buffer = $parser::encode($send_buffer, $this);
67 | if ($send_buffer === '') {
68 | return null;
69 | }
70 | }
71 | return strlen($send_buffer) === stream_socket_sendto($this->_socket, $send_buffer, 0, $this->_remoteAddress);
72 | }
73 |
74 | /**
75 | * Get remote IP.
76 | *
77 | * @return string
78 | */
79 | public function getRemoteIp()
80 | {
81 | $pos = strrpos($this->_remoteAddress, ':');
82 | if ($pos) {
83 | return trim(substr($this->_remoteAddress, 0, $pos), '[]');
84 | }
85 | return '';
86 | }
87 |
88 | /**
89 | * Get remote port.
90 | *
91 | * @return int
92 | */
93 | public function getRemotePort()
94 | {
95 | if ($this->_remoteAddress) {
96 | return (int)substr(strrchr($this->_remoteAddress, ':'), 1);
97 | }
98 | return 0;
99 | }
100 |
101 | /**
102 | * Close connection.
103 | *
104 | * @param mixed $data
105 | * @param bool $raw
106 | * @return bool
107 | */
108 | public function close($data = null, $raw = false)
109 | {
110 | if ($data !== null) {
111 | $this->send($data, $raw);
112 | }
113 | return true;
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Connection/AsyncUdpConnection.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Connection;
15 |
16 | use Workerman\Events\EventInterface;
17 | use Workerman\Worker;
18 | use Exception;
19 |
20 | /**
21 | * AsyncTcpConnection.
22 | */
23 | class AsyncUdpConnection extends UdpConnection
24 | {
25 | /**
26 | * Construct.
27 | *
28 | * @param string $remote_address
29 | * @throws Exception
30 | */
31 | public function __construct($remote_address)
32 | {
33 | // Get the application layer communication protocol and listening address.
34 | list($scheme, $address) = explode(':', $remote_address, 2);
35 | // Check application layer protocol class.
36 | if ($scheme !== 'udp') {
37 | $scheme = ucfirst($scheme);
38 | $this->protocol = '\\Protocols\\' . $scheme;
39 | if (!class_exists($this->protocol)) {
40 | $this->protocol = "\\Workerman\\Protocols\\$scheme";
41 | if (!class_exists($this->protocol)) {
42 | throw new Exception("class \\Protocols\\$scheme not exist");
43 | }
44 | }
45 | }
46 |
47 | $this->_remoteAddress = substr($address, 2);
48 | $this->_socket = stream_socket_client("udp://{$this->_remoteAddress}");
49 | Worker::$globalEvent->add($this->_socket, EventInterface::EV_READ, array($this, 'baseRead'));
50 | }
51 |
52 | /**
53 | * For udp package.
54 | *
55 | * @param resource $socket
56 | * @return bool
57 | */
58 | public function baseRead($socket)
59 | {
60 | $recv_buffer = stream_socket_recvfrom($socket, Worker::MAX_UDP_PACKAGE_SIZE, 0, $remote_address);
61 | if (false === $recv_buffer || empty($remote_address)) {
62 | return false;
63 | }
64 |
65 | if ($this->onMessage) {
66 | if ($this->protocol) {
67 | $parser = $this->protocol;
68 | $recv_buffer = $parser::decode($recv_buffer, $this);
69 | }
70 | ConnectionInterface::$statistics['total_request']++;
71 | try {
72 | call_user_func($this->onMessage, $this, $recv_buffer);
73 | } catch (\Exception $e) {
74 | self::log($e);
75 | exit(250);
76 | } catch (\Error $e) {
77 | self::log($e);
78 | exit(250);
79 | }
80 | }
81 | return true;
82 | }
83 |
84 |
85 | /**
86 | * Close connection.
87 | *
88 | * @param mixed $data
89 | * @return bool
90 | */
91 | public function close($data = null, $raw = false)
92 | {
93 | if ($data !== null) {
94 | $this->send($data, $raw);
95 | }
96 | Worker::$globalEvent->del($this->_socket, EventInterface::EV_READ);
97 | fclose($this->_socket);
98 | return true;
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/_lib/ape/http/mime.types:
--------------------------------------------------------------------------------
1 |
2 | types {
3 | text/html html htm shtml;
4 | text/css css;
5 | text/xml xml;
6 | image/gif gif;
7 | image/jpeg jpeg jpg;
8 | application/x-javascript js;
9 | application/atom+xml atom;
10 | application/rss+xml rss;
11 |
12 | text/mathml mml;
13 | text/plain txt;
14 | text/vnd.sun.j2me.app-descriptor jad;
15 | text/vnd.wap.wml wml;
16 | text/x-component htc;
17 |
18 | image/png png;
19 | image/tiff tif tiff;
20 | image/vnd.wap.wbmp wbmp;
21 | image/x-icon ico;
22 | image/x-jng jng;
23 | image/x-ms-bmp bmp;
24 | image/svg+xml svg svgz;
25 | image/webp webp;
26 |
27 | application/java-archive jar war ear;
28 | application/mac-binhex40 hqx;
29 | application/msword doc;
30 | application/pdf pdf;
31 | application/postscript ps eps ai;
32 | application/rtf rtf;
33 | application/vnd.ms-excel xls;
34 | application/vnd.ms-powerpoint ppt;
35 | application/vnd.wap.wmlc wmlc;
36 | application/vnd.google-earth.kml+xml kml;
37 | application/vnd.google-earth.kmz kmz;
38 | application/x-7z-compressed 7z;
39 | application/x-cocoa cco;
40 | application/x-java-archive-diff jardiff;
41 | application/x-java-jnlp-file jnlp;
42 | application/x-makeself run;
43 | application/x-perl pl pm;
44 | application/x-pilot prc pdb;
45 | application/x-rar-compressed rar;
46 | application/x-redhat-package-manager rpm;
47 | application/x-sea sea;
48 | application/x-shockwave-flash swf;
49 | application/x-stuffit sit;
50 | application/x-tcl tcl tk;
51 | application/x-x509-ca-cert der pem crt;
52 | application/x-xpinstall xpi;
53 | application/xhtml+xml xhtml;
54 | application/zip zip;
55 |
56 | application/octet-stream bin exe dll;
57 | application/octet-stream deb;
58 | application/octet-stream dmg;
59 | application/octet-stream eot;
60 | application/octet-stream iso img;
61 | application/octet-stream msi msp msm;
62 |
63 | audio/midi mid midi kar;
64 | audio/mpeg mp3;
65 | audio/ogg ogg;
66 | audio/x-m4a m4a;
67 | audio/x-realaudio ra;
68 |
69 | video/3gpp 3gpp 3gp;
70 | video/mp4 mp4;
71 | video/mpeg mpeg mpg;
72 | video/quicktime mov;
73 | video/webm webm;
74 | video/x-flv flv;
75 | video/x-m4v m4v;
76 | video/x-mng mng;
77 | video/x-ms-asf asx asf;
78 | video/x-ms-wmv wmv;
79 | video/x-msvideo avi;
80 | }
81 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Protocols/Http/mime.types:
--------------------------------------------------------------------------------
1 |
2 | types {
3 | text/html html htm shtml;
4 | text/css css;
5 | text/xml xml;
6 | image/gif gif;
7 | image/jpeg jpeg jpg;
8 | application/x-javascript js;
9 | application/atom+xml atom;
10 | application/rss+xml rss;
11 |
12 | text/mathml mml;
13 | text/plain txt;
14 | text/vnd.sun.j2me.app-descriptor jad;
15 | text/vnd.wap.wml wml;
16 | text/x-component htc;
17 |
18 | image/png png;
19 | image/tiff tif tiff;
20 | image/vnd.wap.wbmp wbmp;
21 | image/x-icon ico;
22 | image/x-jng jng;
23 | image/x-ms-bmp bmp;
24 | image/svg+xml svg svgz;
25 | image/webp webp;
26 |
27 | application/java-archive jar war ear;
28 | application/mac-binhex40 hqx;
29 | application/msword doc;
30 | application/pdf pdf;
31 | application/postscript ps eps ai;
32 | application/rtf rtf;
33 | application/vnd.ms-excel xls;
34 | application/vnd.ms-powerpoint ppt;
35 | application/vnd.wap.wmlc wmlc;
36 | application/vnd.google-earth.kml+xml kml;
37 | application/vnd.google-earth.kmz kmz;
38 | application/x-7z-compressed 7z;
39 | application/x-cocoa cco;
40 | application/x-java-archive-diff jardiff;
41 | application/x-java-jnlp-file jnlp;
42 | application/x-makeself run;
43 | application/x-perl pl pm;
44 | application/x-pilot prc pdb;
45 | application/x-rar-compressed rar;
46 | application/x-redhat-package-manager rpm;
47 | application/x-sea sea;
48 | application/x-shockwave-flash swf;
49 | application/x-stuffit sit;
50 | application/x-tcl tcl tk;
51 | application/x-x509-ca-cert der pem crt;
52 | application/x-xpinstall xpi;
53 | application/xhtml+xml xhtml;
54 | application/zip zip;
55 |
56 | application/octet-stream bin exe dll;
57 | application/octet-stream deb;
58 | application/octet-stream dmg;
59 | application/octet-stream eot;
60 | application/octet-stream iso img;
61 | application/octet-stream msi msp msm;
62 |
63 | audio/midi mid midi kar;
64 | audio/mpeg mp3;
65 | audio/ogg ogg;
66 | audio/x-m4a m4a;
67 | audio/x-realaudio ra;
68 |
69 | video/3gpp 3gpp 3gp;
70 | video/mp4 mp4;
71 | video/mpeg mpeg mpg;
72 | video/quicktime mov;
73 | video/webm webm;
74 | video/x-flv flv;
75 | video/x-m4v m4v;
76 | video/x-mng mng;
77 | video/x-ms-asf asx asf;
78 | video/x-ms-wmv wmv;
79 | video/x-msvideo avi;
80 | }
81 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Protocols/Http/mime.types:
--------------------------------------------------------------------------------
1 |
2 | types {
3 | text/html html htm shtml;
4 | text/css css;
5 | text/xml xml;
6 | image/gif gif;
7 | image/jpeg jpeg jpg;
8 | application/x-javascript js;
9 | application/atom+xml atom;
10 | application/rss+xml rss;
11 |
12 | text/mathml mml;
13 | text/plain txt;
14 | text/vnd.sun.j2me.app-descriptor jad;
15 | text/vnd.wap.wml wml;
16 | text/x-component htc;
17 |
18 | image/png png;
19 | image/tiff tif tiff;
20 | image/vnd.wap.wbmp wbmp;
21 | image/x-icon ico;
22 | image/x-jng jng;
23 | image/x-ms-bmp bmp;
24 | image/svg+xml svg svgz;
25 | image/webp webp;
26 |
27 | application/java-archive jar war ear;
28 | application/mac-binhex40 hqx;
29 | application/msword doc;
30 | application/pdf pdf;
31 | application/postscript ps eps ai;
32 | application/rtf rtf;
33 | application/vnd.ms-excel xls;
34 | application/vnd.ms-powerpoint ppt;
35 | application/vnd.wap.wmlc wmlc;
36 | application/vnd.google-earth.kml+xml kml;
37 | application/vnd.google-earth.kmz kmz;
38 | application/x-7z-compressed 7z;
39 | application/x-cocoa cco;
40 | application/x-java-archive-diff jardiff;
41 | application/x-java-jnlp-file jnlp;
42 | application/x-makeself run;
43 | application/x-perl pl pm;
44 | application/x-pilot prc pdb;
45 | application/x-rar-compressed rar;
46 | application/x-redhat-package-manager rpm;
47 | application/x-sea sea;
48 | application/x-shockwave-flash swf;
49 | application/x-stuffit sit;
50 | application/x-tcl tcl tk;
51 | application/x-x509-ca-cert der pem crt;
52 | application/x-xpinstall xpi;
53 | application/xhtml+xml xhtml;
54 | application/zip zip;
55 |
56 | application/octet-stream bin exe dll;
57 | application/octet-stream deb;
58 | application/octet-stream dmg;
59 | application/octet-stream eot;
60 | application/octet-stream iso img;
61 | application/octet-stream msi msp msm;
62 |
63 | audio/midi mid midi kar;
64 | audio/mpeg mp3;
65 | audio/ogg ogg;
66 | audio/x-m4a m4a;
67 | audio/x-realaudio ra;
68 |
69 | video/3gpp 3gpp 3gp;
70 | video/mp4 mp4;
71 | video/mpeg mpeg mpg;
72 | video/quicktime mov;
73 | video/webm webm;
74 | video/x-flv flv;
75 | video/x-m4v m4v;
76 | video/x-mng mng;
77 | video/x-ms-asf asx asf;
78 | video/x-ms-wmv wmv;
79 | video/x-msvideo avi;
80 | }
81 |
--------------------------------------------------------------------------------
/_lib/ape/Router.php:
--------------------------------------------------------------------------------
1 | 2) {
62 | // 当前模块的路径
63 | ApeWeb::$MODULE_URL = ApeWeb::$HOME . $url_arr [0] . "/";
64 | ApeWeb::$MODULE_NAME = "z_" . $url_arr [0];
65 |
66 | $module_name = "z_" . $url_arr [0] . DS;
67 | $controller_path = "controller" . DS;
68 |
69 | for ($i = 1; $i < (count($url_arr) - 2); $i ++) {
70 | $controller_path = $controller_path . $url_arr [$i] . DS;
71 | }
72 |
73 | $controller_name = ucfirst($url_arr [count($url_arr) - 2]);
74 | // 将$controller_name里面的'_'后面的第一个字符换成大写的
75 | while (true) {
76 | if ($controller_name_index = strpos($controller_name, "_")) {
77 | $controller_name = substr_replace($controller_name, strtoupper($controller_name {$controller_name_index + 1}), $controller_name_index, 2);
78 | } else {
79 | break;
80 | }
81 | }
82 | $method_name = $url_arr [count($url_arr) - 1];
83 | }
84 |
85 | // 检查拦截器
86 | foreach ($map as $route) {
87 | if (stripos($url, $route [0]) === 0) {
88 | $filter [] = $route [1];
89 | }
90 | }
91 |
92 | // 循环中间件
93 | if (isset($filter)) {
94 | try {
95 | foreach ($filter as $cl) {
96 | $cuf_bool = call_user_func($cl, $data);
97 | // 如果拦截器终止了,那么退出整次解析
98 | if ($cuf_bool == false) {
99 | return false;
100 | }
101 | }
102 | } catch (\Exception $e) {
103 | // Jump_exit?
104 | if ($e->getMessage() != 'jump_exit') {
105 | $access_log [5] = $e;
106 | }
107 | $code = $e->getCode() ? $e->getCode() : 500;
108 | $access_log [6] = 500;
109 | }
110 | }
111 | return true;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/_lib/ape/http/Sendfile.php:
--------------------------------------------------------------------------------
1 | getRemoteIp ();
48 | $_SERVER ['REMOTE_PORT'] = $connection->getRemotePort ();
49 | include $file_path;
50 | } catch ( \Exception $e ) {
51 | // Jump_exit?
52 | if ($e->getMessage () != 'jump_exit') {
53 | echo $e;
54 | }
55 | }
56 | $content = ob_get_clean ();
57 | ini_set ( 'display_errors', 'on' );
58 | if (strtolower ( $_SERVER ['HTTP_CONNECTION'] ) === "keep-alive") {
59 | $connection->send ( $content );
60 | } else {
61 | $connection->close ( $content );
62 | }
63 | return;
64 | }
65 | // Check 304.
66 | $info = stat ( $file_path );
67 | $modified_time = $info ? date ( 'D, d M Y H:i:s', $info ['mtime'] ) . ' GMT' : '';
68 | if (! empty ( $_SERVER ['HTTP_IF_MODIFIED_SINCE'] ) && $info) {
69 | // Http 304.
70 | if ($modified_time === $_SERVER ['HTTP_IF_MODIFIED_SINCE']) {
71 | // 304
72 | Http::header ( 'HTTP/1.1 304 Not Modified' );
73 | // Send nothing but http headers..
74 | $connection->close ( '' );
75 | return;
76 | }
77 | }
78 |
79 | // Http header.
80 | if ($modified_time) {
81 | $modified_time = "Last-Modified: $modified_time\r\n";
82 | }
83 | $file_size = filesize ( $file_path );
84 | $file_info = pathinfo ( $file_path );
85 | $extension = isset ( $file_info ['extension'] ) ? $file_info ['extension'] : '';
86 | $file_name = isset ( $file_info ['filename'] ) ? $file_info ['filename'] : '';
87 | $file_name = $file_name . $hz;
88 | $header = "HTTP/1.1 200 OK\r\n";
89 | if (isset ( self::$mimeTypeMap [$extension] )) {
90 | $header .= "Content-Type: " . self::$mimeTypeMap [$extension] . "\r\n";
91 | } else {
92 | $header .= "Content-Type: application/octet-stream\r\n";
93 | $header .= "Content-Disposition: attachment; filename=\"$file_name\"\r\n";
94 | }
95 | $header .= "Connection: keep-alive\r\n";
96 | $header .= $modified_time;
97 | $header .= "Content-Length: $file_size\r\n\r\n";
98 | $trunk_limit_size = 1024 * 1024 * 10;
99 | if ($file_size < $trunk_limit_size) {
100 | $connection->send ( $header . file_get_contents ( $file_path ), true );
101 | //$connection->close();
102 | return;
103 | }
104 | $connection->send ( $header, true );
105 |
106 | // Read file content from disk piece by piece and send to client.
107 | $connection->fileHandler = fopen ( $file_path, 'r' );
108 | $do_write = function () use ($connection) {
109 | // Send buffer not full.
110 | while ( empty ( $connection->bufferFull ) ) {
111 | // Read from disk.
112 | $buffer = fread ( $connection->fileHandler, 8192 );
113 | // Read eof.
114 | if ($buffer === '' || $buffer === false) {
115 | return;
116 | }
117 | $connection->send ( $buffer, true );
118 | }
119 | //$connection->close();
120 | };
121 |
122 | // Send buffer full.
123 | $connection->onBufferFull = function ($connection) {
124 | $connection->bufferFull = true;
125 | };
126 | // Send buffer drain.
127 | $connection->onBufferDrain = function ($connection) use ($do_write) {
128 | $connection->bufferFull = false;
129 | $do_write ();
130 | };
131 | $do_write ();
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Events/Ev.php:
--------------------------------------------------------------------------------
1 |
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events;
15 |
16 | use Workerman\Worker;
17 |
18 | /**
19 | * ev eventloop
20 | */
21 | class Ev implements EventInterface {
22 | /**
23 | * All listeners for read/write event.
24 | *
25 | * @var array
26 | */
27 | protected $_allEvents = array ();
28 |
29 | /**
30 | * Event listeners of signal.
31 | *
32 | * @var array
33 | */
34 | protected $_eventSignal = array ();
35 |
36 | /**
37 | * All timer event listeners.
38 | * [func, args, event, flag, time_interval]
39 | *
40 | * @var array
41 | */
42 | protected $_eventTimer = array ();
43 |
44 | /**
45 | * Timer id.
46 | *
47 | * @var int
48 | */
49 | protected static $_timerId = 1;
50 |
51 | /**
52 | * Add a timer.
53 | *
54 | * {@inheritdoc}
55 | *
56 | */
57 | public function add($fd, $flag, $func, $args = null) {
58 | $callback = function ($event, $socket) use ($fd, $func) {
59 | try {
60 | call_user_func ( $func, $fd );
61 | } catch ( \Exception $e ) {
62 | Worker::log ( $e );
63 | exit ( 250 );
64 | } catch ( \Error $e ) {
65 | Worker::log ( $e );
66 | exit ( 250 );
67 | }
68 | };
69 |
70 | switch ($flag) {
71 | case self::EV_SIGNAL :
72 | $event = new \EvSignal ( $fd, $callback );
73 | $this->_eventSignal [$fd] = $event;
74 | return true;
75 | case self::EV_TIMER :
76 | case self::EV_TIMER_ONCE :
77 | $repeat = $flag == self::EV_TIMER_ONCE ? 0 : $fd;
78 | $param = array (
79 | $func,
80 | ( array ) $args,
81 | $flag,
82 | $fd,
83 | self::$_timerId
84 | );
85 | $event = new \EvTimer ( $fd, $repeat, array (
86 | $this,
87 | 'timerCallback'
88 | ), $param );
89 | $this->_eventTimer [self::$_timerId] = $event;
90 | return self::$_timerId ++;
91 | default :
92 | $fd_key = ( int ) $fd;
93 | $real_flag = $flag === self::EV_READ ? \Ev::READ : \Ev::WRITE;
94 | $event = new \EvIo ( $fd, $real_flag, $callback );
95 | $this->_allEvents [$fd_key] [$flag] = $event;
96 | return true;
97 | }
98 | }
99 |
100 | /**
101 | * Remove a timer.
102 | *
103 | * {@inheritdoc}
104 | *
105 | */
106 | public function del($fd, $flag) {
107 | switch ($flag) {
108 | case self::EV_READ :
109 | case self::EV_WRITE :
110 | $fd_key = ( int ) $fd;
111 | if (isset ( $this->_allEvents [$fd_key] [$flag] )) {
112 | $this->_allEvents [$fd_key] [$flag]->stop ();
113 | unset ( $this->_allEvents [$fd_key] [$flag] );
114 | }
115 | if (empty ( $this->_allEvents [$fd_key] )) {
116 | unset ( $this->_allEvents [$fd_key] );
117 | }
118 | break;
119 | case self::EV_SIGNAL :
120 | $fd_key = ( int ) $fd;
121 | if (isset ( $this->_eventSignal [$fd_key] )) {
122 | $this->_allEvents [$fd_key] [$flag]->stop ();
123 | unset ( $this->_eventSignal [$fd_key] );
124 | }
125 | break;
126 | case self::EV_TIMER :
127 | case self::EV_TIMER_ONCE :
128 | if (isset ( $this->_eventTimer [$fd] )) {
129 | $this->_eventTimer [$fd]->stop ();
130 | unset ( $this->_eventTimer [$fd] );
131 | }
132 | break;
133 | }
134 | return true;
135 | }
136 |
137 | /**
138 | * Timer callback.
139 | *
140 | * @param \EvWatcher $event
141 | */
142 | public function timerCallback($event) {
143 | $param = $event->data;
144 | $timer_id = $param [4];
145 | if ($param [2] === self::EV_TIMER_ONCE) {
146 | $this->_eventTimer [$timer_id]->stop ();
147 | unset ( $this->_eventTimer [$timer_id] );
148 | }
149 | try {
150 | call_user_func_array ( $param [0], $param [1] );
151 | } catch ( \Exception $e ) {
152 | Worker::log ( $e );
153 | exit ( 250 );
154 | } catch ( \Error $e ) {
155 | Worker::log ( $e );
156 | exit ( 250 );
157 | }
158 | }
159 |
160 | /**
161 | * Remove all timers.
162 | *
163 | * @return void
164 | */
165 | public function clearAllTimer() {
166 | foreach ( $this->_eventTimer as $event ) {
167 | $event->stop ();
168 | }
169 | $this->_eventTimer = array ();
170 | }
171 |
172 | /**
173 | * Main loop.
174 | *
175 | * @see EventInterface::loop()
176 | */
177 | public function loop() {
178 | \Ev::run ();
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # workerman_web_ape
2 | 使用workerman封装的一个完整的web框架,不依赖任何其他服务,比如nginx等,自己实现了静态服务,MVC封装,支持分布式部署,性能强悍,框架优化很多细节,使用非常简单。
3 | 性能是传统php开发的10倍以上,传送门 http://www.workerman.net/bench
4 | 由于所有代码都是php实现,所以可控性非常好
5 |
6 | ## Requires
7 | PHP7 or 更高
8 | A POSIX compatible operating system (Linux, OSX, BSD)
9 | POSIX PCNTL extensions for PHP
10 |
11 | ## 路由详解
12 | 路由:根据url找寻controller下面的类和方法
13 | 规则 : http://路径/模块名字/类名/方法名
14 | ```http://127.0.0.1/admin/user_mm/all 对应z_admin模块下UserMmController类all方法```
15 | ```http://127.0.0.1/user_mm/all 对应默认模块下UserMmController类all方法```
16 | ```http://127.0.0.1/all 对应默认模块下默认Controller类all方法```
17 | 首先会将url中带_后面的首字母大写,然后查找对应的类和方法
18 |
19 |
20 | ## 数据库操作详解
21 | 使用workerman提供的mysql操作类为基础,封装了find update delete count all page 等方法
22 | 可配置 真/假删除 $softDelete=true/false
23 | 数据库主键必须是id int类型
24 | 如果出现修改id的情况 使用Model::update("修改后数组",原id)
25 |
26 | ## 视图
27 | 封装了简单的输出 循环 判断 include标签,具体看例子,复杂的调用请使用php语法,或者自己扩展
28 | ```
29 | //循环输出
30 | {foreach $n['list'] k2=>n2}
31 | //请使用单引号
32 | {$n2['name']}
33 | //判断
34 | {if $n2['id']==0}
35 | 测试
36 | {/if}
37 | {/foreach}
38 |
39 | //包含文件
40 | {include file="public.head"}
41 |
42 | ```
43 |
44 | ## 日志
45 | 请使用dd_log("相对于log目录的文件夹","日志内容");
46 | ```
47 | 框架会使用和http端口相同的端口创建一个udp服务,所有日志操作都是udp操作,无阻塞。
48 | ```
49 | ## 如何启动
50 | ```php main start ```
51 | ```php main start -d ```
52 | ```php main status ```
53 | ```php main connections```
54 | ```php main stop ```
55 | ```php main restart ```
56 | ```php main reload ```
57 | ```windows环境下需要分别启动根目录下start_*.php文件 ```
58 |
59 | # Workerman性能测试
60 | ```
61 | CPU: Intel(R) Core(TM) i3-3220 CPU @ 3.30GHz and 4 processors totally
62 | Memory: 8G
63 | OS: Ubuntu 14.04 LTS
64 | Software: ab
65 | PHP: 5.5.9
66 | ```
67 |
68 | **Codes**
69 | ```php
70 | count=3;
74 | $worker->onMessage = function($connection, $data)
75 | {
76 | $connection->send("HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nServer: workerman\r\nContent-Length: 5\r\n\r\nhello");
77 | };
78 | Worker::runAll();
79 | ```
80 | **Result**
81 |
82 | ```shell
83 | ab -n1000000 -c100 -k http://127.0.0.1:1234/
84 | This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
85 | Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
86 | Licensed to The Apache Software Foundation, http://www.apache.org/
87 |
88 | Benchmarking 127.0.0.1 (be patient)
89 | Completed 100000 requests
90 | Completed 200000 requests
91 | Completed 300000 requests
92 | Completed 400000 requests
93 | Completed 500000 requests
94 | Completed 600000 requests
95 | Completed 700000 requests
96 | Completed 800000 requests
97 | Completed 900000 requests
98 | Completed 1000000 requests
99 | Finished 1000000 requests
100 |
101 |
102 | Server Software: workerman/3.1.4
103 | Server Hostname: 127.0.0.1
104 | Server Port: 1234
105 |
106 | Document Path: /
107 | Document Length: 5 bytes
108 |
109 | Concurrency Level: 100
110 | Time taken for tests: 7.240 seconds
111 | Complete requests: 1000000
112 | Failed requests: 0
113 | Keep-Alive requests: 1000000
114 | Total transferred: 73000000 bytes
115 | HTML transferred: 5000000 bytes
116 | Requests per second: 138124.14 [#/sec] (mean)
117 | Time per request: 0.724 [ms] (mean)
118 | Time per request: 0.007 [ms] (mean, across all concurrent requests)
119 | Transfer rate: 9846.74 [Kbytes/sec] received
120 |
121 | Connection Times (ms)
122 | min mean[+/-sd] median max
123 | Connect: 0 0 0.0 0 5
124 | Processing: 0 1 0.2 1 9
125 | Waiting: 0 1 0.2 1 9
126 | Total: 0 1 0.2 1 9
127 |
128 | Percentage of the requests served within a certain time (ms)
129 | 50% 1
130 | 66% 1
131 | 75% 1
132 | 80% 1
133 | 90% 1
134 | 95% 1
135 | 98% 1
136 | 99% 1
137 | 100% 9 (longest request)
138 |
139 | ```
140 | ## Workerman的使用方法
141 |
142 | 中文主页:[http://www.workerman.net](http://www.workerman.net)
143 |
144 | 中文文档: [http://doc.workerman.net](http://doc.workerman.net)
145 |
146 | Documentation:[https://github.com/walkor/workerman-manual](https://github.com/walkor/workerman-manual/blob/master/english/src/SUMMARY.md)
147 |
148 |
149 |
150 | ## 其他
151 | 因为workerman代码实例化一次并放在内存中运行 所以开发与传统php开发有些差别
152 | 由于使用workerman为基础,请先阅读workerman手册,一些workerman注意事项本文未提出。
153 | 参考:Navigation框架 https://github.com/xpader/Navigation
154 | 参考:WebWorker框架 https://github.com/xtgxiso/WebWorker
155 | 修改了ueediter部分代码,使其适应本框架
156 |
157 |
158 | ## 联系我
159 |
160 | QQ群: 1098698769
161 | 任何人都可以通过QQ群联系到我。
162 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Lib/Timer.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Lib;
15 |
16 | use Workerman\Events\EventInterface;
17 | use Exception;
18 |
19 | /**
20 | * Timer.
21 | *
22 | * example:
23 | * Workerman\Lib\Timer::add($time_interval, callback, array($arg1, $arg2..));
24 | */
25 | class Timer
26 | {
27 | /**
28 | * Tasks that based on ALARM signal.
29 | * [
30 | * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]],
31 | * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]],
32 | * ..
33 | * ]
34 | *
35 | * @var array
36 | */
37 | protected static $_tasks = array();
38 |
39 | /**
40 | * event
41 | *
42 | * @var \Workerman\Events\EventInterface
43 | */
44 | protected static $_event = null;
45 |
46 | /**
47 | * Init.
48 | *
49 | * @param \Workerman\Events\EventInterface $event
50 | * @return void
51 | */
52 | public static function init($event = null)
53 | {
54 | if ($event) {
55 | self::$_event = $event;
56 | } else {
57 | pcntl_signal(SIGALRM, array('\Workerman\Lib\Timer', 'signalHandle'), false);
58 | }
59 | }
60 |
61 | /**
62 | * ALARM signal handler.
63 | *
64 | * @return void
65 | */
66 | public static function signalHandle()
67 | {
68 | if (!self::$_event) {
69 | pcntl_alarm(1);
70 | self::tick();
71 | }
72 | }
73 |
74 | /**
75 | * Add a timer.
76 | *
77 | * @param int $time_interval
78 | * @param callback $func
79 | * @param mixed $args
80 | * @param bool $persistent
81 | * @return bool
82 | */
83 | public static function add($time_interval, $func, $args = array(), $persistent = true)
84 | {
85 | if ($time_interval <= 0) {
86 | echo new Exception("bad time_interval");
87 | return false;
88 | }
89 |
90 | if (self::$_event) {
91 | return self::$_event->add($time_interval,
92 | $persistent ? EventInterface::EV_TIMER : EventInterface::EV_TIMER_ONCE, $func, $args);
93 | }
94 |
95 | if (!is_callable($func)) {
96 | echo new Exception("not callable");
97 | return false;
98 | }
99 |
100 | if (empty(self::$_tasks)) {
101 | pcntl_alarm(1);
102 | }
103 |
104 | $time_now = time();
105 | $run_time = $time_now + $time_interval;
106 | if (!isset(self::$_tasks[$run_time])) {
107 | self::$_tasks[$run_time] = array();
108 | }
109 | self::$_tasks[$run_time][] = array($func, (array)$args, $persistent, $time_interval);
110 | return true;
111 | }
112 |
113 |
114 | /**
115 | * Tick.
116 | *
117 | * @return void
118 | */
119 | public static function tick()
120 | {
121 | if (empty(self::$_tasks)) {
122 | pcntl_alarm(0);
123 | return;
124 | }
125 |
126 | $time_now = time();
127 | foreach (self::$_tasks as $run_time => $task_data) {
128 | if ($time_now >= $run_time) {
129 | foreach ($task_data as $index => $one_task) {
130 | $task_func = $one_task[0];
131 | $task_args = $one_task[1];
132 | $persistent = $one_task[2];
133 | $time_interval = $one_task[3];
134 | try {
135 | call_user_func_array($task_func, $task_args);
136 | } catch (\Exception $e) {
137 | echo $e;
138 | }
139 | if ($persistent) {
140 | self::add($time_interval, $task_func, $task_args);
141 | }
142 | }
143 | unset(self::$_tasks[$run_time]);
144 | }
145 | }
146 | }
147 |
148 | /**
149 | * Remove a timer.
150 | *
151 | * @param mixed $timer_id
152 | * @return bool
153 | */
154 | public static function del($timer_id)
155 | {
156 | if (self::$_event) {
157 | return self::$_event->del($timer_id, EventInterface::EV_TIMER);
158 | }
159 |
160 | return false;
161 | }
162 |
163 | /**
164 | * Remove all timers.
165 | *
166 | * @return void
167 | */
168 | public static function delAll()
169 | {
170 | self::$_tasks = array();
171 | pcntl_alarm(0);
172 | if (self::$_event) {
173 | self::$_event->clearAllTimer();
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Lib/Timer.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Lib;
15 |
16 | use Workerman\Events\EventInterface;
17 | use Exception;
18 |
19 | /**
20 | * Timer.
21 | *
22 | * example:
23 | * Workerman\Lib\Timer::add($time_interval, callback, array($arg1, $arg2..));
24 | */
25 | class Timer
26 | {
27 | /**
28 | * Tasks that based on ALARM signal.
29 | * [
30 | * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]],
31 | * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]],
32 | * ..
33 | * ]
34 | *
35 | * @var array
36 | */
37 | protected static $_tasks = array();
38 |
39 | /**
40 | * event
41 | *
42 | * @var \Workerman\Events\EventInterface
43 | */
44 | protected static $_event = null;
45 |
46 | /**
47 | * Init.
48 | *
49 | * @param \Workerman\Events\EventInterface $event
50 | * @return void
51 | */
52 | public static function init($event = null)
53 | {
54 | if ($event) {
55 | self::$_event = $event;
56 | } else {
57 | pcntl_signal(SIGALRM, array('\Workerman\Lib\Timer', 'signalHandle'), false);
58 | }
59 | }
60 |
61 | /**
62 | * ALARM signal handler.
63 | *
64 | * @return void
65 | */
66 | public static function signalHandle()
67 | {
68 | if (!self::$_event) {
69 | pcntl_alarm(1);
70 | self::tick();
71 | }
72 | }
73 |
74 | /**
75 | * Add a timer.
76 | *
77 | * @param int $time_interval
78 | * @param callback $func
79 | * @param mixed $args
80 | * @param bool $persistent
81 | * @return int/false
82 | */
83 | public static function add($time_interval, $func, $args = array(), $persistent = true)
84 | {
85 | if ($time_interval <= 0) {
86 | echo new Exception("bad time_interval");
87 | return false;
88 | }
89 |
90 | if (self::$_event) {
91 | return self::$_event->add($time_interval,
92 | $persistent ? EventInterface::EV_TIMER : EventInterface::EV_TIMER_ONCE, $func, $args);
93 | }
94 |
95 | if (!is_callable($func)) {
96 | echo new Exception("not callable");
97 | return false;
98 | }
99 |
100 | if (empty(self::$_tasks)) {
101 | pcntl_alarm(1);
102 | }
103 |
104 | $time_now = time();
105 | $run_time = $time_now + $time_interval;
106 | if (!isset(self::$_tasks[$run_time])) {
107 | self::$_tasks[$run_time] = array();
108 | }
109 | self::$_tasks[$run_time][] = array($func, (array)$args, $persistent, $time_interval);
110 | return 1;
111 | }
112 |
113 |
114 | /**
115 | * Tick.
116 | *
117 | * @return void
118 | */
119 | public static function tick()
120 | {
121 | if (empty(self::$_tasks)) {
122 | pcntl_alarm(0);
123 | return;
124 | }
125 |
126 | $time_now = time();
127 | foreach (self::$_tasks as $run_time => $task_data) {
128 | if ($time_now >= $run_time) {
129 | foreach ($task_data as $index => $one_task) {
130 | $task_func = $one_task[0];
131 | $task_args = $one_task[1];
132 | $persistent = $one_task[2];
133 | $time_interval = $one_task[3];
134 | try {
135 | call_user_func_array($task_func, $task_args);
136 | } catch (\Exception $e) {
137 | echo $e;
138 | }
139 | if ($persistent) {
140 | self::add($time_interval, $task_func, $task_args);
141 | }
142 | }
143 | unset(self::$_tasks[$run_time]);
144 | }
145 | }
146 | }
147 |
148 | /**
149 | * Remove a timer.
150 | *
151 | * @param mixed $timer_id
152 | * @return bool
153 | */
154 | public static function del($timer_id)
155 | {
156 | if (self::$_event) {
157 | return self::$_event->del($timer_id, EventInterface::EV_TIMER);
158 | }
159 |
160 | return false;
161 | }
162 |
163 | /**
164 | * Remove all timers.
165 | *
166 | * @return void
167 | */
168 | public static function delAll()
169 | {
170 | self::$_tasks = array();
171 | pcntl_alarm(0);
172 | if (self::$_event) {
173 | self::$_event->clearAllTimer();
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Events/React/ExtEventLoop.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events\React;
15 | use Workerman\Events\EventInterface;
16 |
17 | /**
18 | * Class ExtEventLoop
19 | * @package Workerman\Events\React
20 | */
21 | class ExtEventLoop extends \React\EventLoop\ExtEventLoop
22 | {
23 | /**
24 | * Event base.
25 | *
26 | * @var EventBase
27 | */
28 | protected $_eventBase = null;
29 |
30 | /**
31 | * All signal Event instances.
32 | *
33 | * @var array
34 | */
35 | protected $_signalEvents = array();
36 |
37 | /**
38 | * @var array
39 | */
40 | protected $_timerIdMap = array();
41 |
42 | /**
43 | * @var int
44 | */
45 | protected $_timerIdIndex = 0;
46 |
47 | /**
48 | * Add event listener to event loop.
49 | *
50 | * @param $fd
51 | * @param $flag
52 | * @param $func
53 | * @param array $args
54 | * @return bool
55 | */
56 | public function add($fd, $flag, $func, $args = array())
57 | {
58 | $args = (array)$args;
59 | switch ($flag) {
60 | case EventInterface::EV_READ:
61 | return $this->addReadStream($fd, $func);
62 | case EventInterface::EV_WRITE:
63 | return $this->addWriteStream($fd, $func);
64 | case EventInterface::EV_SIGNAL:
65 | return $this->addSignal($fd, $func);
66 | case EventInterface::EV_TIMER:
67 | $timer_obj = $this->addPeriodicTimer($fd, function() use ($func, $args) {
68 | call_user_func_array($func, $args);
69 | });
70 | $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
71 | return $this->_timerIdIndex;
72 | case EventInterface::EV_TIMER_ONCE:
73 | $timer_obj = $this->addTimer($fd, function() use ($func, $args) {
74 | call_user_func_array($func, $args);
75 | });
76 | $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
77 | return $this->_timerIdIndex;
78 | }
79 | return false;
80 | }
81 |
82 | /**
83 | * Remove event listener from event loop.
84 | *
85 | * @param mixed $fd
86 | * @param int $flag
87 | * @return bool
88 | */
89 | public function del($fd, $flag)
90 | {
91 | switch ($flag) {
92 | case EventInterface::EV_READ:
93 | return $this->removeReadStream($fd);
94 | case EventInterface::EV_WRITE:
95 | return $this->removeWriteStream($fd);
96 | case EventInterface::EV_SIGNAL:
97 | return $this->removeSignal($fd);
98 | case EventInterface::EV_TIMER:
99 | case EventInterface::EV_TIMER_ONCE;
100 | if (isset($this->_timerIdMap[$fd])){
101 | $timer_obj = $this->_timerIdMap[$fd];
102 | unset($this->_timerIdMap[$fd]);
103 | $this->cancelTimer($timer_obj);
104 | return true;
105 | }
106 | }
107 | return false;
108 | }
109 |
110 |
111 | /**
112 | * Main loop.
113 | *
114 | * @return void
115 | */
116 | public function loop()
117 | {
118 | $this->run();
119 | }
120 |
121 | /**
122 | * Construct
123 | */
124 | public function __construct()
125 | {
126 | parent::__construct();
127 | $class = new \ReflectionClass('\React\EventLoop\ExtEventLoop');
128 | $property = $class->getProperty('eventBase');
129 | $property->setAccessible(true);
130 | $this->_eventBase = $property->getValue($this);
131 | }
132 |
133 | /**
134 | * Add signal handler.
135 | *
136 | * @param $signal
137 | * @param $callback
138 | * @return bool
139 | */
140 | public function addSignal($signal, $callback)
141 | {
142 | $event = \Event::signal($this->_eventBase, $signal, $callback);
143 | if (!$event||!$event->add()) {
144 | return false;
145 | }
146 | $this->_signalEvents[$signal] = $event;
147 | }
148 |
149 | /**
150 | * Remove signal handler.
151 | *
152 | * @param $signal
153 | */
154 | public function removeSignal($signal)
155 | {
156 | if (isset($this->_signalEvents[$signal])) {
157 | $this->_signalEvents[$signal]->del();
158 | unset($this->_signalEvents[$signal]);
159 | }
160 | }
161 |
162 | /**
163 | * Destroy loop.
164 | *
165 | * @return void
166 | */
167 | public function destroy()
168 | {
169 | foreach ($this->_signalEvents as $event) {
170 | $event->del();
171 | }
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Events/React/LibEventLoop.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events\React;
15 | use Workerman\Events\EventInterface;
16 |
17 | /**
18 | * Class LibEventLoop
19 | * @package Workerman\Events\React
20 | */
21 | class LibEventLoop extends \React\EventLoop\LibEventLoop
22 | {
23 | /**
24 | * Event base.
25 | *
26 | * @var event_base resource
27 | */
28 | protected $_eventBase = null;
29 |
30 | /**
31 | * All signal Event instances.
32 | *
33 | * @var array
34 | */
35 | protected $_signalEvents = array();
36 |
37 | /**
38 | * @var array
39 | */
40 | protected $_timerIdMap = array();
41 |
42 | /**
43 | * @var int
44 | */
45 | protected $_timerIdIndex = 0;
46 |
47 | /**
48 | * Add event listener to event loop.
49 | *
50 | * @param $fd
51 | * @param $flag
52 | * @param $func
53 | * @param array $args
54 | * @return bool
55 | */
56 | public function add($fd, $flag, $func, $args = array())
57 | {
58 | $args = (array)$args;
59 | switch ($flag) {
60 | case EventInterface::EV_READ:
61 | return $this->addReadStream($fd, $func);
62 | case EventInterface::EV_WRITE:
63 | return $this->addWriteStream($fd, $func);
64 | case EventInterface::EV_SIGNAL:
65 | return $this->addSignal($fd, $func);
66 | case EventInterface::EV_TIMER:
67 | $timer_obj = $this->addPeriodicTimer($fd, function() use ($func, $args) {
68 | call_user_func_array($func, $args);
69 | });
70 | $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
71 | return $this->_timerIdIndex;
72 | case EventInterface::EV_TIMER_ONCE:
73 | $timer_obj = $this->addTimer($fd, function() use ($func, $args) {
74 | call_user_func_array($func, $args);
75 | });
76 | $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
77 | return $this->_timerIdIndex;
78 | }
79 | return false;
80 | }
81 |
82 | /**
83 | * Remove event listener from event loop.
84 | *
85 | * @param mixed $fd
86 | * @param int $flag
87 | * @return bool
88 | */
89 | public function del($fd, $flag)
90 | {
91 | switch ($flag) {
92 | case EventInterface::EV_READ:
93 | return $this->removeReadStream($fd);
94 | case EventInterface::EV_WRITE:
95 | return $this->removeWriteStream($fd);
96 | case EventInterface::EV_SIGNAL:
97 | return $this->removeSignal($fd);
98 | case EventInterface::EV_TIMER:
99 | case EventInterface::EV_TIMER_ONCE;
100 | if (isset($this->_timerIdMap[$fd])){
101 | $timer_obj = $this->_timerIdMap[$fd];
102 | unset($this->_timerIdMap[$fd]);
103 | $this->cancelTimer($timer_obj);
104 | return true;
105 | }
106 | }
107 | return false;
108 | }
109 |
110 |
111 | /**
112 | * Main loop.
113 | *
114 | * @return void
115 | */
116 | public function loop()
117 | {
118 | $this->run();
119 | }
120 |
121 | /**
122 | * Construct.
123 | */
124 | public function __construct()
125 | {
126 | parent::__construct();
127 | $class = new \ReflectionClass('\React\EventLoop\LibEventLoop');
128 | $property = $class->getProperty('eventBase');
129 | $property->setAccessible(true);
130 | $this->_eventBase = $property->getValue($this);
131 | }
132 |
133 | /**
134 | * Add signal handler.
135 | *
136 | * @param $signal
137 | * @param $callback
138 | * @return bool
139 | */
140 | public function addSignal($signal, $callback)
141 | {
142 | $event = event_new();
143 | $this->_signalEvents[$signal] = $event;
144 | event_set($event, $signal, EV_SIGNAL | EV_PERSIST, $callback);
145 | event_base_set($event, $this->_eventBase);
146 | event_add($event);
147 | }
148 |
149 | /**
150 | * Remove signal handler.
151 | *
152 | * @param $signal
153 | */
154 | public function removeSignal($signal)
155 | {
156 | if (isset($this->_signalEvents[$signal])) {
157 | $event = $this->_signalEvents[$signal];
158 | event_del($event);
159 | unset($this->_signalEvents[$signal]);
160 | }
161 | }
162 |
163 | /**
164 | * Destroy loop.
165 | *
166 | * @return void
167 | */
168 | public function destroy()
169 | {
170 | foreach ($this->_signalEvents as $event) {
171 | event_del($event);
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Events/React/StreamSelectLoop.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events\React;
15 | use Workerman\Events\EventInterface;
16 |
17 | /**
18 | * Class StreamSelectLoop
19 | * @package Workerman\Events\React
20 | */
21 | class StreamSelectLoop extends \React\EventLoop\StreamSelectLoop
22 | {
23 | /**
24 | * @var array
25 | */
26 | protected $_timerIdMap = array();
27 |
28 | /**
29 | * @var int
30 | */
31 | protected $_timerIdIndex = 0;
32 |
33 | /**
34 | * Add event listener to event loop.
35 | *
36 | * @param $fd
37 | * @param $flag
38 | * @param $func
39 | * @param array $args
40 | * @return bool
41 | */
42 | public function add($fd, $flag, $func, $args = array())
43 | {
44 | $args = (array)$args;
45 | switch ($flag) {
46 | case EventInterface::EV_READ:
47 | return $this->addReadStream($fd, $func);
48 | case EventInterface::EV_WRITE:
49 | return $this->addWriteStream($fd, $func);
50 | case EventInterface::EV_SIGNAL:
51 | return $this->addSignal($fd, $func);
52 | case EventInterface::EV_TIMER:
53 | $timer_obj = $this->addPeriodicTimer($fd, function() use ($func, $args) {
54 | call_user_func_array($func, $args);
55 | });
56 | $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
57 | return $this->_timerIdIndex;
58 | case EventInterface::EV_TIMER_ONCE:
59 | $timer_obj = $this->addTimer($fd, function() use ($func, $args) {
60 | call_user_func_array($func, $args);
61 | });
62 | $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
63 | return $this->_timerIdIndex;
64 | }
65 | return false;
66 | }
67 |
68 | /**
69 | * Remove event listener from event loop.
70 | *
71 | * @param mixed $fd
72 | * @param int $flag
73 | * @return bool
74 | */
75 | public function del($fd, $flag)
76 | {
77 | switch ($flag) {
78 | case EventInterface::EV_READ:
79 | return $this->removeReadStream($fd);
80 | case EventInterface::EV_WRITE:
81 | return $this->removeWriteStream($fd);
82 | case EventInterface::EV_SIGNAL:
83 | return $this->removeSignal($fd);
84 | case EventInterface::EV_TIMER:
85 | case EventInterface::EV_TIMER_ONCE;
86 | if (isset($this->_timerIdMap[$fd])){
87 | $timer_obj = $this->_timerIdMap[$fd];
88 | unset($this->_timerIdMap[$fd]);
89 | $this->cancelTimer($timer_obj);
90 | return true;
91 | }
92 | }
93 | return false;
94 | }
95 |
96 |
97 | /**
98 | * Main loop.
99 | *
100 | * @return void
101 | */
102 | public function loop()
103 | {
104 | $this->run();
105 | }
106 |
107 | /**
108 | * Add signal handler.
109 | *
110 | * @param $signal
111 | * @param $callback
112 | * @return bool
113 | */
114 | public function addSignal($signal, $callback)
115 | {
116 | if(PHP_EOL !== "\r\n") {
117 | pcntl_signal($signal, $callback);
118 | }
119 | }
120 |
121 | /**
122 | * Remove signal handler.
123 | *
124 | * @param $signal
125 | */
126 | public function removeSignal($signal)
127 | {
128 | if(PHP_EOL !== "\r\n") {
129 | pcntl_signal($signal, SIG_IGN);
130 | }
131 | }
132 |
133 | /**
134 | * Emulate a stream_select() implementation that does not break when passed
135 | * empty stream arrays.
136 | *
137 | * @param array &$read An array of read streams to select upon.
138 | * @param array &$write An array of write streams to select upon.
139 | * @param integer|null $timeout Activity timeout in microseconds, or null to wait forever.
140 | *
141 | * @return integer|false The total number of streams that are ready for read/write.
142 | * Can return false if stream_select() is interrupted by a signal.
143 | */
144 | protected function streamSelect(array &$read, array &$write, $timeout)
145 | {
146 | if ($read || $write) {
147 | $except = null;
148 | // Calls signal handlers for pending signals
149 | pcntl_signal_dispatch();
150 | // suppress warnings that occur, when stream_select is interrupted by a signal
151 | return @stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout);
152 | }
153 |
154 | // Calls signal handlers for pending signals
155 | if(PHP_EOL !== "\r\n") {
156 | pcntl_signal_dispatch();
157 | }
158 | $timeout && usleep($timeout);
159 |
160 | return 0;
161 | }
162 |
163 | /**
164 | * Destroy loop.
165 | *
166 | * @return void
167 | */
168 | public function destroy()
169 | {
170 |
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Events/Ev.php:
--------------------------------------------------------------------------------
1 |
10 | * @link http://www.workerman.net/
11 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
12 | */
13 | namespace Workerman\Events;
14 |
15 | use Workerman\Worker;
16 |
17 | /**
18 | * ev eventloop
19 | */
20 | class Ev implements EventInterface
21 | {
22 | /**
23 | * All listeners for read/write event.
24 | *
25 | * @var array
26 | */
27 | protected $_allEvents = array();
28 |
29 | /**
30 | * Event listeners of signal.
31 | *
32 | * @var array
33 | */
34 | protected $_eventSignal = array();
35 |
36 | /**
37 | * All timer event listeners.
38 | * [func, args, event, flag, time_interval]
39 | *
40 | * @var array
41 | */
42 | protected $_eventTimer = array();
43 |
44 | /**
45 | * Timer id.
46 | *
47 | * @var int
48 | */
49 | protected static $_timerId = 1;
50 |
51 | /**
52 | * Add a timer.
53 | * {@inheritdoc}
54 | */
55 | public function add($fd, $flag, $func, $args = null)
56 | {
57 | $callback = function ($event, $socket) use ($fd, $func) {
58 | try {
59 | call_user_func($func, $fd);
60 | } catch (\Exception $e) {
61 | Worker::log($e);
62 | exit(250);
63 | } catch (\Error $e) {
64 | Worker::log($e);
65 | exit(250);
66 | }
67 | };
68 | switch ($flag) {
69 | case self::EV_SIGNAL:
70 | $event = new \EvSignal($fd, $callback);
71 | $this->_eventSignal[$fd] = $event;
72 | return true;
73 | case self::EV_TIMER:
74 | case self::EV_TIMER_ONCE:
75 | $repeat = $flag == self::EV_TIMER_ONCE ? 0 : $fd;
76 | $param = array($func, (array)$args, $flag, $fd, self::$_timerId);
77 | $event = new \EvTimer($fd, $repeat, array($this, 'timerCallback'), $param);
78 | $this->_eventTimer[self::$_timerId] = $event;
79 | return self::$_timerId++;
80 | default :
81 | $fd_key = (int)$fd;
82 | $real_flag = $flag === self::EV_READ ? \Ev::READ : \Ev::WRITE;
83 | $event = new \EvIo($fd, $real_flag, $callback);
84 | $this->_allEvents[$fd_key][$flag] = $event;
85 | return true;
86 | }
87 |
88 | }
89 |
90 | /**
91 | * Remove a timer.
92 | * {@inheritdoc}
93 | */
94 | public function del($fd, $flag)
95 | {
96 | switch ($flag) {
97 | case self::EV_READ:
98 | case self::EV_WRITE:
99 | $fd_key = (int)$fd;
100 | if (isset($this->_allEvents[$fd_key][$flag])) {
101 | $this->_allEvents[$fd_key][$flag]->stop();
102 | unset($this->_allEvents[$fd_key][$flag]);
103 | }
104 | if (empty($this->_allEvents[$fd_key])) {
105 | unset($this->_allEvents[$fd_key]);
106 | }
107 | break;
108 | case self::EV_SIGNAL:
109 | $fd_key = (int)$fd;
110 | if (isset($this->_eventSignal[$fd_key])) {
111 | $this->_eventSignal[$fd_key]->stop();
112 | unset($this->_eventSignal[$fd_key]);
113 | }
114 | break;
115 | case self::EV_TIMER:
116 | case self::EV_TIMER_ONCE:
117 | if (isset($this->_eventTimer[$fd])) {
118 | $this->_eventTimer[$fd]->stop();
119 | unset($this->_eventTimer[$fd]);
120 | }
121 | break;
122 | }
123 | return true;
124 | }
125 |
126 | /**
127 | * Timer callback.
128 | *
129 | * @param \EvWatcher $event
130 | */
131 | public function timerCallback($event)
132 | {
133 | $param = $event->data;
134 | $timer_id = $param[4];
135 | if ($param[2] === self::EV_TIMER_ONCE) {
136 | $this->_eventTimer[$timer_id]->stop();
137 | unset($this->_eventTimer[$timer_id]);
138 | }
139 | try {
140 | call_user_func_array($param[0], $param[1]);
141 | } catch (\Exception $e) {
142 | Worker::log($e);
143 | exit(250);
144 | } catch (\Error $e) {
145 | Worker::log($e);
146 | exit(250);
147 | }
148 | }
149 |
150 | /**
151 | * Remove all timers.
152 | *
153 | * @return void
154 | */
155 | public function clearAllTimer()
156 | {
157 | foreach ($this->_eventTimer as $event) {
158 | $event->stop();
159 | }
160 | $this->_eventTimer = array();
161 | }
162 |
163 | /**
164 | * Main loop.
165 | *
166 | * @see EventInterface::loop()
167 | */
168 | public function loop()
169 | {
170 | \Ev::run();
171 | }
172 |
173 | /**
174 | * Destroy loop.
175 | *
176 | * @return void
177 | */
178 | public function destroy()
179 | {
180 | foreach ($this->_allEvents as $event) {
181 | $event->stop();
182 | }
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Events/Event.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright 有个鬼<42765633@qq.com>
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events;
15 |
16 | use Workerman\Worker;
17 |
18 | /**
19 | * libevent eventloop
20 | */
21 | class Event implements EventInterface
22 | {
23 | /**
24 | * Event base.
25 | * @var object
26 | */
27 | protected $_eventBase = null;
28 |
29 | /**
30 | * All listeners for read/write event.
31 | * @var array
32 | */
33 | protected $_allEvents = array();
34 |
35 | /**
36 | * Event listeners of signal.
37 | * @var array
38 | */
39 | protected $_eventSignal = array();
40 |
41 | /**
42 | * All timer event listeners.
43 | * [func, args, event, flag, time_interval]
44 | * @var array
45 | */
46 | protected $_eventTimer = array();
47 |
48 | /**
49 | * Timer id.
50 | * @var int
51 | */
52 | protected static $_timerId = 1;
53 |
54 | /**
55 | * construct
56 | * @return void
57 | */
58 | public function __construct()
59 | {
60 | $this->_eventBase = new \EventBase();
61 | }
62 |
63 | /**
64 | * @see EventInterface::add()
65 | */
66 | public function add($fd, $flag, $func, $args=array())
67 | {
68 | switch ($flag) {
69 | case self::EV_SIGNAL:
70 |
71 | $fd_key = (int)$fd;
72 | $event = \Event::signal($this->_eventBase, $fd, $func);
73 | if (!$event||!$event->add()) {
74 | return false;
75 | }
76 | $this->_eventSignal[$fd_key] = $event;
77 | return true;
78 |
79 | case self::EV_TIMER:
80 | case self::EV_TIMER_ONCE:
81 |
82 | $param = array($func, (array)$args, $flag, $fd, self::$_timerId);
83 | $event = new \Event($this->_eventBase, -1, \Event::TIMEOUT|\Event::PERSIST, array($this, "timerCallback"), $param);
84 | if (!$event||!$event->addTimer($fd)) {
85 | return false;
86 | }
87 | $this->_eventTimer[self::$_timerId] = $event;
88 | return self::$_timerId++;
89 |
90 | default :
91 | $fd_key = (int)$fd;
92 | $real_flag = $flag === self::EV_READ ? \Event::READ | \Event::PERSIST : \Event::WRITE | \Event::PERSIST;
93 | $event = new \Event($this->_eventBase, $fd, $real_flag, $func, $fd);
94 | if (!$event||!$event->add()) {
95 | return false;
96 | }
97 | $this->_allEvents[$fd_key][$flag] = $event;
98 | return true;
99 | }
100 | }
101 |
102 | /**
103 | * @see Events\EventInterface::del()
104 | */
105 | public function del($fd, $flag)
106 | {
107 | switch ($flag) {
108 |
109 | case self::EV_READ:
110 | case self::EV_WRITE:
111 |
112 | $fd_key = (int)$fd;
113 | if (isset($this->_allEvents[$fd_key][$flag])) {
114 | $this->_allEvents[$fd_key][$flag]->del();
115 | unset($this->_allEvents[$fd_key][$flag]);
116 | }
117 | if (empty($this->_allEvents[$fd_key])) {
118 | unset($this->_allEvents[$fd_key]);
119 | }
120 | break;
121 |
122 | case self::EV_SIGNAL:
123 |
124 | $fd_key = (int)$fd;
125 | if (isset($this->_eventSignal[$fd_key])) {
126 | $this->_allEvents[$fd_key][$flag]->del();
127 | unset($this->_eventSignal[$fd_key]);
128 | }
129 | break;
130 |
131 | case self::EV_TIMER:
132 | case self::EV_TIMER_ONCE:
133 | if (isset($this->_eventTimer[$fd])) {
134 | $this->_eventTimer[$fd]->del();
135 | unset($this->_eventTimer[$fd]);
136 | }
137 | break;
138 | }
139 | return true;
140 | }
141 |
142 | /**
143 | * Timer callback.
144 | * @param null $fd
145 | * @param int $what
146 | * @param int $timer_id
147 | */
148 | public function timerCallback($fd, $what, $param)
149 | {
150 | $timer_id = $param[4];
151 |
152 | if ($param[2] === self::EV_TIMER_ONCE) {
153 | $this->_eventTimer[$timer_id]->del();
154 | unset($this->_eventTimer[$timer_id]);
155 | }
156 |
157 | try {
158 | call_user_func_array($param[0], $param[1]);
159 | } catch (\Exception $e) {
160 | Worker::log($e);
161 | exit(250);
162 | } catch (\Error $e) {
163 | Worker::log($e);
164 | exit(250);
165 | }
166 | }
167 |
168 | /**
169 | * @see Events\EventInterface::clearAllTimer()
170 | * @return void
171 | */
172 | public function clearAllTimer()
173 | {
174 | foreach ($this->_eventTimer as $event) {
175 | $event->del();
176 | }
177 | $this->_eventTimer = array();
178 | }
179 |
180 |
181 | /**
182 | * @see EventInterface::loop()
183 | */
184 | public function loop()
185 | {
186 | $this->_eventBase->loop();
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Events/Event.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright 有个鬼<42765633@qq.com>
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events;
15 |
16 | use Workerman\Worker;
17 |
18 | /**
19 | * libevent eventloop
20 | */
21 | class Event implements EventInterface
22 | {
23 | /**
24 | * Event base.
25 | * @var object
26 | */
27 | protected $_eventBase = null;
28 |
29 | /**
30 | * All listeners for read/write event.
31 | * @var array
32 | */
33 | protected $_allEvents = array();
34 |
35 | /**
36 | * Event listeners of signal.
37 | * @var array
38 | */
39 | protected $_eventSignal = array();
40 |
41 | /**
42 | * All timer event listeners.
43 | * [func, args, event, flag, time_interval]
44 | * @var array
45 | */
46 | protected $_eventTimer = array();
47 |
48 | /**
49 | * Timer id.
50 | * @var int
51 | */
52 | protected static $_timerId = 1;
53 |
54 | /**
55 | * construct
56 | * @return void
57 | */
58 | public function __construct()
59 | {
60 | $this->_eventBase = new \EventBase();
61 | }
62 |
63 | /**
64 | * @see EventInterface::add()
65 | */
66 | public function add($fd, $flag, $func, $args=array())
67 | {
68 | switch ($flag) {
69 | case self::EV_SIGNAL:
70 |
71 | $fd_key = (int)$fd;
72 | $event = \Event::signal($this->_eventBase, $fd, $func);
73 | if (!$event||!$event->add()) {
74 | return false;
75 | }
76 | $this->_eventSignal[$fd_key] = $event;
77 | return true;
78 |
79 | case self::EV_TIMER:
80 | case self::EV_TIMER_ONCE:
81 |
82 | $param = array($func, (array)$args, $flag, $fd, self::$_timerId);
83 | $event = new \Event($this->_eventBase, -1, \Event::TIMEOUT|\Event::PERSIST, array($this, "timerCallback"), $param);
84 | if (!$event||!$event->addTimer($fd)) {
85 | return false;
86 | }
87 | $this->_eventTimer[self::$_timerId] = $event;
88 | return self::$_timerId++;
89 |
90 | default :
91 | $fd_key = (int)$fd;
92 | $real_flag = $flag === self::EV_READ ? \Event::READ | \Event::PERSIST : \Event::WRITE | \Event::PERSIST;
93 | $event = new \Event($this->_eventBase, $fd, $real_flag, $func, $fd);
94 | if (!$event||!$event->add()) {
95 | return false;
96 | }
97 | $this->_allEvents[$fd_key][$flag] = $event;
98 | return true;
99 | }
100 | }
101 |
102 | /**
103 | * @see Events\EventInterface::del()
104 | */
105 | public function del($fd, $flag)
106 | {
107 | switch ($flag) {
108 |
109 | case self::EV_READ:
110 | case self::EV_WRITE:
111 |
112 | $fd_key = (int)$fd;
113 | if (isset($this->_allEvents[$fd_key][$flag])) {
114 | $this->_allEvents[$fd_key][$flag]->del();
115 | unset($this->_allEvents[$fd_key][$flag]);
116 | }
117 | if (empty($this->_allEvents[$fd_key])) {
118 | unset($this->_allEvents[$fd_key]);
119 | }
120 | break;
121 |
122 | case self::EV_SIGNAL:
123 | $fd_key = (int)$fd;
124 | if (isset($this->_eventSignal[$fd_key])) {
125 | $this->_eventSignal[$fd_key]->del();
126 | unset($this->_eventSignal[$fd_key]);
127 | }
128 | break;
129 |
130 | case self::EV_TIMER:
131 | case self::EV_TIMER_ONCE:
132 | if (isset($this->_eventTimer[$fd])) {
133 | $this->_eventTimer[$fd]->del();
134 | unset($this->_eventTimer[$fd]);
135 | }
136 | break;
137 | }
138 | return true;
139 | }
140 |
141 | /**
142 | * Timer callback.
143 | * @param null $fd
144 | * @param int $what
145 | * @param int $timer_id
146 | */
147 | public function timerCallback($fd, $what, $param)
148 | {
149 | $timer_id = $param[4];
150 |
151 | if ($param[2] === self::EV_TIMER_ONCE) {
152 | $this->_eventTimer[$timer_id]->del();
153 | unset($this->_eventTimer[$timer_id]);
154 | }
155 |
156 | try {
157 | call_user_func_array($param[0], $param[1]);
158 | } catch (\Exception $e) {
159 | Worker::log($e);
160 | exit(250);
161 | } catch (\Error $e) {
162 | Worker::log($e);
163 | exit(250);
164 | }
165 | }
166 |
167 | /**
168 | * @see Events\EventInterface::clearAllTimer()
169 | * @return void
170 | */
171 | public function clearAllTimer()
172 | {
173 | foreach ($this->_eventTimer as $event) {
174 | $event->del();
175 | }
176 | $this->_eventTimer = array();
177 | }
178 |
179 |
180 | /**
181 | * @see EventInterface::loop()
182 | */
183 | public function loop()
184 | {
185 | $this->_eventBase->loop();
186 | }
187 |
188 | /**
189 | * Destroy loop.
190 | *
191 | * @return void
192 | */
193 | public function destroy()
194 | {
195 | foreach ($this->_eventSignal as $event) {
196 | $event->del();
197 | }
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/_lib/ape/helper.php:
--------------------------------------------------------------------------------
1 | ";
88 | ApeWeb::$SEND_BODY = ApeWeb::$SEND_BODY . "";
89 | return true;
90 | }
91 |
92 | /**
93 | * 返回上一页的js脚本
94 | */
95 | function history_back() {
96 | ApeWeb::$SEND_BODY = ApeWeb::$SEND_BODY . "";
97 | }
98 |
99 | // 重定向方法,url需要传递相对于views的路径
100 | function R($url, $arr = array()) {
101 | $en = strpos ( $url, "http" );
102 | if ($en !== 0) {
103 | $url = ApeWeb::$MODULE_URL . $url;
104 | }
105 | // 跳转默认是当前模块
106 | if (count ( $arr ) <= 0) {
107 | ApeWeb::$SEND_BODY = ApeWeb::$SEND_BODY . "";
108 | } else {
109 | $str = "";
110 | $str = "";
115 | $str = $str . "";
116 | ApeWeb::$SEND_BODY = ApeWeb::$SEND_BODY . $str;
117 | }
118 | return true;
119 | }
120 |
121 | /**
122 | * 发送api
123 | */
124 | function api($msg, $code, $content) {
125 | Http::header ( "Content-type: application/json" );
126 | $arr ["msg"] = $msg;
127 | $arr ["code"] = $code;
128 | $arr ["content"] = $content;
129 | ApeWeb::$SEND_BODY = ApeWeb::$SEND_BODY . json_encode ( $arr );
130 | return true;
131 | }
132 |
133 | /**
134 | * 返回页面
135 | */
136 | function view($tpl, &$arr = array()) {
137 | ApeWeb::$SEND_BODY = ApeWeb::$SEND_BODY . ApeWeb::$view->view ( $tpl, $arr );
138 | return true;
139 | }
140 |
141 | /**
142 | * 随机数
143 | *
144 | * @param unknown $length
145 | * @param string $chars
146 | * @return string
147 | */
148 | function random($length, $chars = '1234567890qwertyuiopasdfghjklzxcvbnm') {
149 | $hash = '';
150 | $max = strlen ( $chars ) - 1;
151 | for($i = 0; $i < $length; $i ++) {
152 | $hash .= $chars [mt_rand ( 0, $max )];
153 | }
154 | return $hash;
155 | }
156 |
157 | /**
158 | * 清理 HTML 中的 XSS 潜在威胁
159 | * 参考:https://github.com/xpader/Navigation
160 | * 千辛万苦写出来,捣鼓正则累死人
161 | *
162 | * @param string|array $string
163 | * @param bool $strict
164 | * 严格模式下,iframe 等元素也会被过滤
165 | * @return mixed
166 | */
167 | function clean_xss($string, $strict = true) {
168 | if (is_array ( $string )) {
169 | return array_map ( 'cleanXss', $string );
170 | }
171 |
172 | // 移除不可见的字符
173 | $string = preg_replace ( '/%0[0-8bcef]/', '', $string );
174 | $string = preg_replace ( '/%1[0-9a-f]/', '', $string );
175 | $string = preg_replace ( '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $string );
176 |
177 | $string = preg_replace ( '//is', '', $string ); // 过滤 meta 标签
178 | $string = preg_replace ( '//is', '', $string ); // 过滤 link 标签
179 | $string = preg_replace ( '//is', '', $string ); // 过滤 script 标签
180 |
181 | if ($strict) {
182 | $string = preg_replace ( '//is', '', $string ); // 过滤 style 标签
183 | $string = preg_replace ( '//is', '', $string ); // 过滤 iframe 标签 1
184 | $string = preg_replace ( '//is', '', $string ); // 过滤 iframe 标签 2
185 | }
186 |
187 | $string = preg_replace_callback ( '/(\<\w+\s)(.+?)(?=( \/)?\>)/is', function ($m) {
188 | // 去除标签上的 on.. 开头的 JS 事件,以下一个 xxx= 属性或者尾部为终点
189 | $m [2] = preg_replace ( '/\son[a-z]+\s*\=.+?(\s\w+\s*\=|$)/is', '\1', $m [2] );
190 |
191 | // 去除 A 标签中 href 属性为 javascript: 开头的内容
192 | if (strtolower ( $m [1] ) == '|>)/is', '\1\2', $string ); // 过滤标签尾部多余的空格
201 |
202 | return $string;
203 | }
204 |
205 | /**
206 | * 打印
207 | *
208 | * @param unknown $arr
209 | */
210 | function dd($arr) {
211 | var_dump ( $arr );
212 | }
213 |
214 | function find($model, $id) {
215 | return call_user_func ( "\model\\" . $model . "::find", $id );
216 | }
217 |
218 | /**
219 | * 日志打印
220 | */
221 | function dd_log($msg, $dir = "default") {
222 | if(ApeWeb::$udp_log_client!=null){
223 | $arr ["dir"] = $dir;
224 | $arr ["msg"] = $msg;
225 | ApeWeb::$udp_log_client->send ( json_encode ( $arr ) );
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/_lib/ape/view/View.php:
--------------------------------------------------------------------------------
1 | templatedir . $tpl, 'r');
47 | $text = fread($fp, filesize($this->templatedir . $tpl));
48 | fclose($fp);
49 | // repalce template tag to PHP tag //
50 | $text = str_replace('{/if}', '', $text);
51 | $text = str_replace('{/loop}', '', $text);
52 | $text = str_replace('{foreachelse}', '', $text);
53 | $text = str_replace('{/foreach}', '', $text);
54 | $text = str_replace('{else}', '', $text);
55 | $text = str_replace('{loopelse}', '', $text);
56 | // template pattern tags //
57 | $pattern = array(
58 | '/\$(\w*[a-zA-Z0-9_])/',
59 | '/\$this\-\>vars\[\'(\w*[a-zA-Z0-9_])\'\]+\.(\w*[a-zA-Z0-9])/',
60 | '/\{include file=(\"|\'|)(\w*[a-zA-Z0-9_\.][a-zA-Z]\w*)(\"|\'|)\}/',
61 | '/\{\$this\-\>vars(\[\'(\w*[a-zA-Z0-9_])\'\])(\[\'(\w*[a-zA-Z0-9_])\'\])?\}/',
62 | '/\{if (.*?)\}/',
63 | '/\{elseif (.*?)\}/',
64 | '/\{loop \$(.*) as (\w*[a-zA-Z0-9_])\}/',
65 | '/\{foreach \$(.*) (\w*[a-zA-Z0-9_])\=\>(\w*[a-zA-Z0-9_])\}/'
66 | );
67 | // replacement PHP tags //
68 | $replacement = array(
69 | '$this->vars[\'\1\']',
70 | '$this->vars[\'\1\'][\'\2\']',
71 | 'display(\'\2\')?>',
72 | 'vars\1\3?>',
73 | '',
74 | '',
75 | 'vars[\'\2\']) {?>',
76 | 'vars[\'\2\']=>$this->vars[\'\3\']) {?>'
77 | );
78 | // repalce template tags to PHP tags //
79 | $text = preg_replace($pattern, $replacement, $text);
80 |
81 | // create compile file //
82 | $compliefile = time() . random(10) ."_".posix_getpid(). ".php";
83 | if ($fp = @fopen($this->compiledir . $compliefile, 'w')) {
84 | fputs($fp, $text);
85 | fclose($fp);
86 | }
87 | // 删除旧的模板
88 | @unlink($this->compiledir . $this->tpl_storage [ApeWeb::$MODULE_NAME . "/" . $tpl]);
89 | $this->tpl_storage [ApeWeb::$MODULE_NAME . "/" . $tpl] = $compliefile;
90 | }
91 |
92 | /*
93 | * assigns values to template variables
94 | * @param array|string $k the template variable name(s)
95 | * @param mixed $v the value to assign
96 | */
97 | public function assign($k, $v = null)
98 | {
99 | $this->vars [$k] = $v;
100 | }
101 |
102 | /*
103 | * ste directory where templates are located
104 | * @param string $str (path)
105 | */
106 | public function templateDir($path)
107 | {
108 | $this->templatedir = $this->pathCheck($path);
109 | }
110 |
111 | /*
112 | * set where compiled templates are located
113 | * @param string $str (path)
114 | */
115 | public function compileDir($path)
116 | {
117 | $this->compiledir = $this->pathCheck($path);
118 | }
119 |
120 | /*
121 | * check the path last character
122 | * @param string $str (path)
123 | * @return string
124 | */
125 | public function pathCheck($str)
126 | {
127 | return (preg_match('/\/$/', $str)) ? $str : $str . '/';
128 | }
129 |
130 | /*
131 | * executes & displays the template results
132 | * @param string $tpl (template file)
133 | */
134 | public function display($tpl)
135 | {
136 | // 将.替换成/
137 | $tpl = str_replace('.', '/', $tpl);
138 | $tpl = $tpl . ".html";
139 |
140 | if (! file_exists($this->templatedir . $tpl)) {
141 | return ('can not load template file : ' . $this->templatedir . $tpl);
142 | }
143 | // 判断是否存在这个模板缓存
144 | if (array_key_exists(ApeWeb::$MODULE_NAME . "/" . $tpl, $this->tpl_storage)) {
145 | // 获取模板模板缓存位置
146 | $compliefile = $this->compiledir . $this->tpl_storage [ApeWeb::$MODULE_NAME . "/" . $tpl];
147 | if (! file_exists($compliefile) || filemtime($this->templatedir . $tpl) > filemtime($compliefile)) {
148 | $this->parse($tpl);
149 | }
150 | } else {
151 | // 如果不存在这个模板缓存
152 | $this->parse($tpl);
153 | }
154 | $compliefile = $this->compiledir . $this->tpl_storage [ApeWeb::$MODULE_NAME . "/" . $tpl];
155 | foreach ($this->vars as $k=>$n) {
156 | $$k = $n;
157 | }
158 | // 打开缓存区
159 | ob_start();
160 | include $compliefile;
161 | $contents = ob_get_contents();
162 | ob_end_clean();
163 |
164 | return $contents;
165 | }
166 |
167 | /**
168 | * 渲染
169 | */
170 | public function view($tpl, &$vars = array())
171 | {
172 | $this->templateDir(RUN_DIR . ApeWeb::$MODULE_NAME . "/" . "views/");
173 | $this->compileDir(RUN_DIR . ApeWeb::$MODULE_NAME . "/" . 'storage/views/');
174 |
175 | $this->vars = $vars;
176 | $this->vars ["HOME"] = ApeWeb::$HOME;
177 | $this->vars ["MODULE_URL"] = ApeWeb::$MODULE_URL;
178 |
179 | $ret = $this->display($tpl);
180 | $this->vars = null;
181 | return $ret;
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/_lib/GlobalData/Client.php:
--------------------------------------------------------------------------------
1 | _globalServers = array_values ( ( array ) $servers );
56 | }
57 |
58 | /**
59 | * Connect to global server.
60 | *
61 | * @throws \Exception
62 | */
63 | protected function getConnection($key) {
64 | $offset = crc32 ( $key ) % count ( $this->_globalServers );
65 | if ($offset < 0) {
66 | $offset = - $offset;
67 | }
68 |
69 | if (! isset ( $this->_globalConnections [$offset] ) || feof ( $this->_globalConnections [$offset] )) {
70 | $connection = stream_socket_client ( "tcp://{$this->_globalServers[$offset]}", $code, $msg, $this->timeout );
71 | if (! $connection) {
72 | throw new \Exception ( $msg );
73 | }
74 | stream_set_timeout ( $connection, $this->timeout );
75 | if (class_exists ( '\Workerman\Lib\Timer' ) && php_sapi_name () === 'cli') {
76 | $timer_id = \Workerman\Lib\Timer::add ( $this->pingInterval, function ($connection) use (&$timer_id) {
77 | $buffer = pack ( 'N', 8 ) . "ping";
78 | if (strlen ( $buffer ) !== @fwrite ( $connection, $buffer )) {
79 | @fclose ( $connection );
80 | \Workerman\Lib\Timer::del ( $timer_id );
81 | }
82 | }, array (
83 | $connection
84 | ) );
85 | }
86 | $this->_globalConnections [$offset] = $connection;
87 | }
88 | return $this->_globalConnections [$offset];
89 | }
90 |
91 | /**
92 | * Magic methods __set.
93 | *
94 | * @param string $key
95 | * @param mixed $value
96 | * @throws \Exception
97 | */
98 | public function __set($key, $value) {
99 | $connection = $this->getConnection ( $key );
100 | $this->writeToRemote ( array (
101 | 'cmd' => 'set',
102 | 'key' => $key,
103 | 'value' => $value
104 | ), $connection );
105 | $this->readFromRemote ( $connection );
106 | }
107 |
108 | /**
109 | * Magic methods __isset.
110 | *
111 | * @param string $key
112 | */
113 | public function __isset($key) {
114 | return null !== $this->__get ( $key );
115 | }
116 |
117 | /**
118 | * Magic methods __unset.
119 | *
120 | * @param string $key
121 | * @throws \Exception
122 | */
123 | public function __unset($key) {
124 | $connection = $this->getConnection ( $key );
125 | $this->writeToRemote ( array (
126 | 'cmd' => 'delete',
127 | 'key' => $key
128 | ), $connection );
129 | $this->readFromRemote ( $connection );
130 | }
131 |
132 | /**
133 | * Magic methods __get.
134 | *
135 | * @param string $key
136 | * @throws \Exception
137 | */
138 | public function __get($key) {
139 | $connection = $this->getConnection ( $key );
140 | $this->writeToRemote ( array (
141 | 'cmd' => 'get',
142 | 'key' => $key
143 | ), $connection );
144 | return $this->readFromRemote ( $connection );
145 | }
146 |
147 | /**
148 | * Cas.
149 | *
150 | * @param string $key
151 | * @param mixed $value
152 | * @throws \Exception
153 | */
154 | public function cas($key, $old_value, $new_value) {
155 | $connection = $this->getConnection ( $key );
156 | $this->writeToRemote ( array (
157 | 'cmd' => 'cas',
158 | 'md5' => md5 ( serialize ( $old_value ) ),
159 | 'key' => $key,
160 | 'value' => $new_value
161 | ), $connection );
162 | return $this->readFromRemote ( $connection );
163 | }
164 |
165 | /**
166 | * Add.
167 | *
168 | * @param string $key
169 | * @throws \Exception
170 | */
171 | public function add($key, $value) {
172 | $connection = $this->getConnection ( $key );
173 | $this->writeToRemote ( array (
174 | 'cmd' => 'add',
175 | 'key' => $key,
176 | 'value' => $value
177 | ), $connection );
178 | return $this->readFromRemote ( $connection );
179 | }
180 |
181 | /**
182 | * Increment.
183 | *
184 | * @param string $key
185 | * @throws \Exception
186 | */
187 | public function increment($key, $step = 1) {
188 | $connection = $this->getConnection ( $key );
189 | $this->writeToRemote ( array (
190 | 'cmd' => 'increment',
191 | 'key' => $key,
192 | 'step' => $step
193 | ), $connection );
194 | return $this->readFromRemote ( $connection );
195 | }
196 |
197 | /**
198 | * Write data to global server.
199 | *
200 | * @param string $buffer
201 | */
202 | protected function writeToRemote($data, $connection) {
203 | $buffer = serialize ( $data );
204 | $buffer = pack ( 'N', 4 + strlen ( $buffer ) ) . $buffer;
205 | $len = fwrite ( $connection, $buffer );
206 | if ($len !== strlen ( $buffer )) {
207 | throw new \Exception ( 'writeToRemote fail' );
208 | }
209 | }
210 |
211 | /**
212 | * Read data from global server.
213 | *
214 | * @throws Exception
215 | */
216 | protected function readFromRemote($connection) {
217 | $all_buffer = '';
218 | $total_len = 4;
219 | $head_read = false;
220 | while ( 1 ) {
221 | $buffer = fread ( $connection, 8192 );
222 | if ($buffer === '' || $buffer === false) {
223 | throw new \Exception ( 'readFromRemote fail' );
224 | }
225 | $all_buffer .= $buffer;
226 | $recv_len = strlen ( $all_buffer );
227 | if ($recv_len >= $total_len) {
228 | if ($head_read) {
229 | break;
230 | }
231 | $unpack_data = unpack ( 'Ntotal_length', $all_buffer );
232 | $total_len = $unpack_data ['total_length'];
233 | if ($recv_len >= $total_len) {
234 | break;
235 | }
236 | $head_read = true;
237 | }
238 | }
239 | return unserialize ( substr ( $all_buffer, 4 ) );
240 | }
241 | }
242 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Events/Libevent.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events;
15 |
16 | use Workerman\Worker;
17 |
18 | /**
19 | * libevent eventloop
20 | */
21 | class Libevent implements EventInterface
22 | {
23 | /**
24 | * Event base.
25 | *
26 | * @var resource
27 | */
28 | protected $_eventBase = null;
29 |
30 | /**
31 | * All listeners for read/write event.
32 | *
33 | * @var array
34 | */
35 | protected $_allEvents = array();
36 |
37 | /**
38 | * Event listeners of signal.
39 | *
40 | * @var array
41 | */
42 | protected $_eventSignal = array();
43 |
44 | /**
45 | * All timer event listeners.
46 | * [func, args, event, flag, time_interval]
47 | *
48 | * @var array
49 | */
50 | protected $_eventTimer = array();
51 |
52 | /**
53 | * construct
54 | */
55 | public function __construct()
56 | {
57 | $this->_eventBase = event_base_new();
58 | }
59 |
60 | /**
61 | * {@inheritdoc}
62 | */
63 | public function add($fd, $flag, $func, $args = array())
64 | {
65 | switch ($flag) {
66 | case self::EV_SIGNAL:
67 | $fd_key = (int)$fd;
68 | $real_flag = EV_SIGNAL | EV_PERSIST;
69 | $this->_eventSignal[$fd_key] = event_new();
70 | if (!event_set($this->_eventSignal[$fd_key], $fd, $real_flag, $func, null)) {
71 | return false;
72 | }
73 | if (!event_base_set($this->_eventSignal[$fd_key], $this->_eventBase)) {
74 | return false;
75 | }
76 | if (!event_add($this->_eventSignal[$fd_key])) {
77 | return false;
78 | }
79 | return true;
80 | case self::EV_TIMER:
81 | case self::EV_TIMER_ONCE:
82 | $event = event_new();
83 | $timer_id = (int)$event;
84 | if (!event_set($event, 0, EV_TIMEOUT, array($this, 'timerCallback'), $timer_id)) {
85 | return false;
86 | }
87 |
88 | if (!event_base_set($event, $this->_eventBase)) {
89 | return false;
90 | }
91 |
92 | $time_interval = $fd * 1000000;
93 | if (!event_add($event, $time_interval)) {
94 | return false;
95 | }
96 | $this->_eventTimer[$timer_id] = array($func, (array)$args, $event, $flag, $time_interval);
97 | return $timer_id;
98 |
99 | default :
100 | $fd_key = (int)$fd;
101 | $real_flag = $flag === self::EV_READ ? EV_READ | EV_PERSIST : EV_WRITE | EV_PERSIST;
102 |
103 | $event = event_new();
104 |
105 | if (!event_set($event, $fd, $real_flag, $func, null)) {
106 | return false;
107 | }
108 |
109 | if (!event_base_set($event, $this->_eventBase)) {
110 | return false;
111 | }
112 |
113 | if (!event_add($event)) {
114 | return false;
115 | }
116 |
117 | $this->_allEvents[$fd_key][$flag] = $event;
118 |
119 | return true;
120 | }
121 |
122 | }
123 |
124 | /**
125 | * {@inheritdoc}
126 | */
127 | public function del($fd, $flag)
128 | {
129 | switch ($flag) {
130 | case self::EV_READ:
131 | case self::EV_WRITE:
132 | $fd_key = (int)$fd;
133 | if (isset($this->_allEvents[$fd_key][$flag])) {
134 | event_del($this->_allEvents[$fd_key][$flag]);
135 | unset($this->_allEvents[$fd_key][$flag]);
136 | }
137 | if (empty($this->_allEvents[$fd_key])) {
138 | unset($this->_allEvents[$fd_key]);
139 | }
140 | break;
141 | case self::EV_SIGNAL:
142 | $fd_key = (int)$fd;
143 | if (isset($this->_eventSignal[$fd_key])) {
144 | event_del($this->_eventSignal[$fd_key]);
145 | unset($this->_eventSignal[$fd_key]);
146 | }
147 | break;
148 | case self::EV_TIMER:
149 | case self::EV_TIMER_ONCE:
150 | // 这里 fd 为timerid
151 | if (isset($this->_eventTimer[$fd])) {
152 | event_del($this->_eventTimer[$fd][2]);
153 | unset($this->_eventTimer[$fd]);
154 | }
155 | break;
156 | }
157 | return true;
158 | }
159 |
160 | /**
161 | * Timer callback.
162 | *
163 | * @param mixed $_null1
164 | * @param int $_null2
165 | * @param mixed $timer_id
166 | */
167 | protected function timerCallback($_null1, $_null2, $timer_id)
168 | {
169 | if ($this->_eventTimer[$timer_id][3] === self::EV_TIMER) {
170 | event_add($this->_eventTimer[$timer_id][2], $this->_eventTimer[$timer_id][4]);
171 | }
172 | try {
173 | call_user_func_array($this->_eventTimer[$timer_id][0], $this->_eventTimer[$timer_id][1]);
174 | } catch (\Exception $e) {
175 | Worker::log($e);
176 | exit(250);
177 | } catch (\Error $e) {
178 | Worker::log($e);
179 | exit(250);
180 | }
181 | if (isset($this->_eventTimer[$timer_id]) && $this->_eventTimer[$timer_id][3] === self::EV_TIMER_ONCE) {
182 | $this->del($timer_id, self::EV_TIMER_ONCE);
183 | }
184 | }
185 |
186 | /**
187 | * {@inheritdoc}
188 | */
189 | public function clearAllTimer()
190 | {
191 | foreach ($this->_eventTimer as $task_data) {
192 | event_del($task_data[2]);
193 | }
194 | $this->_eventTimer = array();
195 | }
196 |
197 | /**
198 | * {@inheritdoc}
199 | */
200 | public function loop()
201 | {
202 | event_base_loop($this->_eventBase);
203 | }
204 | }
205 |
206 |
--------------------------------------------------------------------------------
/_lib/ape/StatisticClient.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | /**
15 | * 统计客户端
16 | * @author workerman.net
17 | */
18 | class StatisticClient
19 | {
20 | /**
21 | * [module=>[interface=>time_start, interface=>time_start ...], module=>[interface=>time_start ..], ... ]
22 | * @var array
23 | */
24 | protected static $timeMap = array();
25 |
26 | /**
27 | * 模块接口上报消耗时间记时
28 | * @param string $module
29 | * @param string $interface
30 | * @return void
31 | */
32 | public static function tick($module = '', $interface = '')
33 | {
34 | return self::$timeMap[$module][$interface] = microtime(true);
35 | }
36 |
37 | /**
38 | * 上报统计数据
39 | * @param string $module
40 | * @param string $interface
41 | * @param bool $success
42 | * @param int $code
43 | * @param string $msg
44 | * @param string $report_address
45 | * @return boolean
46 | */
47 | public static function report($module, $interface, $success, $code, $msg, $report_address = '')
48 | {
49 | $report_address = $report_address ? $report_address : 'udp://127.0.0.1:55656';
50 | if(isset(self::$timeMap[$module][$interface]) && self::$timeMap[$module][$interface] > 0)
51 | {
52 | $time_start = self::$timeMap[$module][$interface];
53 | self::$timeMap[$module][$interface] = 0;
54 | }
55 | else if(isset(self::$timeMap['']['']) && self::$timeMap[''][''] > 0)
56 | {
57 | $time_start = self::$timeMap[''][''];
58 | self::$timeMap[''][''] = 0;
59 | }
60 | else
61 | {
62 | $time_start = microtime(true);
63 | }
64 |
65 | $cost_time = microtime(true) - $time_start;
66 |
67 | $bin_data = StatisticProtocol::encode($module, $interface, $cost_time, $success, $code, $msg);
68 |
69 | return self::sendData($report_address, $bin_data);
70 | }
71 |
72 | /**
73 | * 发送数据给统计系统
74 | * @param string $address
75 | * @param string $buffer
76 | * @return boolean
77 | */
78 | public static function sendData($address, $buffer)
79 | {
80 | $socket = stream_socket_client($address);
81 | if(!$socket)
82 | {
83 | return false;
84 | }
85 | return stream_socket_sendto($socket, $buffer) == strlen($buffer);
86 | }
87 |
88 | }
89 |
90 | /**
91 | *
92 | * struct statisticPortocol
93 | * {
94 | * unsigned char module_name_len;
95 | * unsigned char interface_name_len;
96 | * float cost_time;
97 | * unsigned char success;
98 | * int code;
99 | * unsigned short msg_len;
100 | * unsigned int time;
101 | * char[module_name_len] module_name;
102 | * char[interface_name_len] interface_name;
103 | * char[msg_len] msg;
104 | * }
105 | *
106 | * @author workerman.net
107 | */
108 | class StatisticProtocol
109 | {
110 | /**
111 | * 包头长度
112 | * @var integer
113 | */
114 | const PACKAGE_FIXED_LENGTH = 17;
115 |
116 | /**
117 | * udp 包最大长度
118 | * @var integer
119 | */
120 | const MAX_UDP_PACKGE_SIZE = 65507;
121 |
122 | /**
123 | * char类型能保存的最大数值
124 | * @var integer
125 | */
126 | const MAX_CHAR_VALUE = 255;
127 |
128 | /**
129 | * usigned short 能保存的最大数值
130 | * @var integer
131 | */
132 | const MAX_UNSIGNED_SHORT_VALUE = 65535;
133 |
134 | /**
135 | * 编码
136 | * @param string $module
137 | * @param string $interface
138 | * @param float $cost_time
139 | * @param int $success
140 | * @param int $code
141 | * @param string $msg
142 | * @return string
143 | */
144 | public static function encode($module, $interface , $cost_time, $success, $code = 0,$msg = '')
145 | {
146 | // 防止模块名过长
147 | if(strlen($module) > self::MAX_CHAR_VALUE)
148 | {
149 | $module = substr($module, 0, self::MAX_CHAR_VALUE);
150 | }
151 |
152 | // 防止接口名过长
153 | if(strlen($interface) > self::MAX_CHAR_VALUE)
154 | {
155 | $interface = substr($interface, 0, self::MAX_CHAR_VALUE);
156 | }
157 |
158 | // 防止msg过长
159 | $module_name_length = strlen($module);
160 | $interface_name_length = strlen($interface);
161 | $avalible_size = self::MAX_UDP_PACKGE_SIZE - self::PACKAGE_FIXED_LENGTH - $module_name_length - $interface_name_length;
162 | if(strlen($msg) > $avalible_size)
163 | {
164 | $msg = substr($msg, 0, $avalible_size);
165 | }
166 |
167 | // 打包
168 | return pack('CCfCNnN', $module_name_length, $interface_name_length, $cost_time, $success ? 1 : 0, $code, strlen($msg), time()).$module.$interface.$msg;
169 | }
170 |
171 | /**
172 | * 解包
173 | * @param string $bin_data
174 | * @return array
175 | */
176 | public static function decode($bin_data)
177 | {
178 | // 解包
179 | $data = unpack("Cmodule_name_len/Cinterface_name_len/fcost_time/Csuccess/Ncode/nmsg_len/Ntime", $bin_data);
180 | $module = substr($bin_data, self::PACKAGE_FIXED_LENGTH, $data['module_name_len']);
181 | $interface = substr($bin_data, self::PACKAGE_FIXED_LENGTH + $data['module_name_len'], $data['interface_name_len']);
182 | $msg = substr($bin_data, self::PACKAGE_FIXED_LENGTH + $data['module_name_len'] + $data['interface_name_len']);
183 | return array(
184 | 'module' => $module,
185 | 'interface' => $interface,
186 | 'cost_time' => $data['cost_time'],
187 | 'success' => $data['success'],
188 | 'time' => $data['time'],
189 | 'code' => $data['code'],
190 | 'msg' => $msg,
191 | );
192 | }
193 |
194 | }
195 |
196 | if(PHP_SAPI == 'cli' && isset($argv[0]) && $argv[0] == basename(__FILE__))
197 | {
198 | StatisticClient::tick("TestModule", 'TestInterface');
199 | usleep(rand(10000, 600000));
200 | $success = rand(0,1);
201 | $code = rand(300, 400);
202 | $msg = '这个是测试消息';
203 | var_export(StatisticClient::report('TestModule', 'TestInterface', $success, $code, $msg));;
204 | }
205 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Events/Libevent.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events;
15 |
16 | use Workerman\Worker;
17 |
18 | /**
19 | * libevent eventloop
20 | */
21 | class Libevent implements EventInterface
22 | {
23 | /**
24 | * Event base.
25 | *
26 | * @var resource
27 | */
28 | protected $_eventBase = null;
29 |
30 | /**
31 | * All listeners for read/write event.
32 | *
33 | * @var array
34 | */
35 | protected $_allEvents = array();
36 |
37 | /**
38 | * Event listeners of signal.
39 | *
40 | * @var array
41 | */
42 | protected $_eventSignal = array();
43 |
44 | /**
45 | * All timer event listeners.
46 | * [func, args, event, flag, time_interval]
47 | *
48 | * @var array
49 | */
50 | protected $_eventTimer = array();
51 |
52 | /**
53 | * construct
54 | */
55 | public function __construct()
56 | {
57 | $this->_eventBase = event_base_new();
58 | }
59 |
60 | /**
61 | * {@inheritdoc}
62 | */
63 | public function add($fd, $flag, $func, $args = array())
64 | {
65 | switch ($flag) {
66 | case self::EV_SIGNAL:
67 | $fd_key = (int)$fd;
68 | $real_flag = EV_SIGNAL | EV_PERSIST;
69 | $this->_eventSignal[$fd_key] = event_new();
70 | if (!event_set($this->_eventSignal[$fd_key], $fd, $real_flag, $func, null)) {
71 | return false;
72 | }
73 | if (!event_base_set($this->_eventSignal[$fd_key], $this->_eventBase)) {
74 | return false;
75 | }
76 | if (!event_add($this->_eventSignal[$fd_key])) {
77 | return false;
78 | }
79 | return true;
80 | case self::EV_TIMER:
81 | case self::EV_TIMER_ONCE:
82 | $event = event_new();
83 | $timer_id = (int)$event;
84 | if (!event_set($event, 0, EV_TIMEOUT, array($this, 'timerCallback'), $timer_id)) {
85 | return false;
86 | }
87 |
88 | if (!event_base_set($event, $this->_eventBase)) {
89 | return false;
90 | }
91 |
92 | $time_interval = $fd * 1000000;
93 | if (!event_add($event, $time_interval)) {
94 | return false;
95 | }
96 | $this->_eventTimer[$timer_id] = array($func, (array)$args, $event, $flag, $time_interval);
97 | return $timer_id;
98 |
99 | default :
100 | $fd_key = (int)$fd;
101 | $real_flag = $flag === self::EV_READ ? EV_READ | EV_PERSIST : EV_WRITE | EV_PERSIST;
102 |
103 | $event = event_new();
104 |
105 | if (!event_set($event, $fd, $real_flag, $func, null)) {
106 | return false;
107 | }
108 |
109 | if (!event_base_set($event, $this->_eventBase)) {
110 | return false;
111 | }
112 |
113 | if (!event_add($event)) {
114 | return false;
115 | }
116 |
117 | $this->_allEvents[$fd_key][$flag] = $event;
118 |
119 | return true;
120 | }
121 |
122 | }
123 |
124 | /**
125 | * {@inheritdoc}
126 | */
127 | public function del($fd, $flag)
128 | {
129 | switch ($flag) {
130 | case self::EV_READ:
131 | case self::EV_WRITE:
132 | $fd_key = (int)$fd;
133 | if (isset($this->_allEvents[$fd_key][$flag])) {
134 | event_del($this->_allEvents[$fd_key][$flag]);
135 | unset($this->_allEvents[$fd_key][$flag]);
136 | }
137 | if (empty($this->_allEvents[$fd_key])) {
138 | unset($this->_allEvents[$fd_key]);
139 | }
140 | break;
141 | case self::EV_SIGNAL:
142 | $fd_key = (int)$fd;
143 | if (isset($this->_eventSignal[$fd_key])) {
144 | event_del($this->_eventSignal[$fd_key]);
145 | unset($this->_eventSignal[$fd_key]);
146 | }
147 | break;
148 | case self::EV_TIMER:
149 | case self::EV_TIMER_ONCE:
150 | // 这里 fd 为timerid
151 | if (isset($this->_eventTimer[$fd])) {
152 | event_del($this->_eventTimer[$fd][2]);
153 | unset($this->_eventTimer[$fd]);
154 | }
155 | break;
156 | }
157 | return true;
158 | }
159 |
160 | /**
161 | * Timer callback.
162 | *
163 | * @param mixed $_null1
164 | * @param int $_null2
165 | * @param mixed $timer_id
166 | */
167 | protected function timerCallback($_null1, $_null2, $timer_id)
168 | {
169 | if ($this->_eventTimer[$timer_id][3] === self::EV_TIMER) {
170 | event_add($this->_eventTimer[$timer_id][2], $this->_eventTimer[$timer_id][4]);
171 | }
172 | try {
173 | call_user_func_array($this->_eventTimer[$timer_id][0], $this->_eventTimer[$timer_id][1]);
174 | } catch (\Exception $e) {
175 | Worker::log($e);
176 | exit(250);
177 | } catch (\Error $e) {
178 | Worker::log($e);
179 | exit(250);
180 | }
181 | if (isset($this->_eventTimer[$timer_id]) && $this->_eventTimer[$timer_id][3] === self::EV_TIMER_ONCE) {
182 | $this->del($timer_id, self::EV_TIMER_ONCE);
183 | }
184 | }
185 |
186 | /**
187 | * {@inheritdoc}
188 | */
189 | public function clearAllTimer()
190 | {
191 | foreach ($this->_eventTimer as $task_data) {
192 | event_del($task_data[2]);
193 | }
194 | $this->_eventTimer = array();
195 | }
196 |
197 | /**
198 | * {@inheritdoc}
199 | */
200 | public function loop()
201 | {
202 | event_base_loop($this->_eventBase);
203 | }
204 |
205 | /**
206 | * Destroy loop.
207 | *
208 | * @return void
209 | */
210 | public function destroy()
211 | {
212 | foreach ($this->_eventSignal as $event) {
213 | event_del($event);
214 | }
215 | }
216 | }
217 |
218 |
--------------------------------------------------------------------------------
/_lib/ape/base/DBBase.php:
--------------------------------------------------------------------------------
1 | insert(static::$table)->cols($arr)->query();
33 | } else {
34 | $arr ["id"] = $mysql->insert(static::$table)->cols($arr)->query();
35 | }
36 | // 添加存入缓存
37 |
38 | if ($mysql ->cache != null) {
39 | $arr = self::find($arr ["id"]);
40 | $_key = static::$db_name . "_" . "id_cache_" . static::$table . "_" . $arr ["id"];
41 | $mysql ->cache->$_key = $arr;
42 | }
43 | }
44 |
45 | /**
46 | * 修改
47 | * $id可以不传,默认采用$arr里面的id
48 | *
49 | * @param unknown $arr
50 | */
51 | public static function update(&$arr = null, $id = null)
52 | {
53 | $db_name = static::$db_name;
54 | $mysql = ApeWeb::$mysqls[$db_name];
55 | if ($arr == null) {
56 | return false;
57 | }
58 |
59 | if (! isset($arr ["id"])) {
60 | return false;
61 | }
62 | if ($id == null) {
63 | $id = $arr ["id"];
64 | }
65 | $whereStr = "id='" . $id . "'";
66 |
67 | // 判断缓存的数据和新数据是否一模一样,一样的话,不更新
68 | if ($mysql ->cache != null) {
69 | $_key = static::$db_name . "_" . "id_cache_" . static::$table . "_" . $id;
70 | var_export($mysql ->cache->$_key, true);
71 | if (isset($mysql ->cache->$_key) && $id == $arr ["id"] && $mysql ->cache->$_key === $arr) {
72 | return true;
73 | }
74 | }
75 |
76 | // 设置更新时间
77 | $tm = date("Y-m-d H:i:s", time());
78 | $arr [self::$updated_at] = $tm;
79 |
80 | if (array_key_exists(self::$deleted_at, $arr)) {
81 | if ($arr [self::$deleted_at] == null) {
82 | unset($arr [self::$deleted_at]);
83 | }
84 | }
85 |
86 | if ($mysql->update(static::$table)->cols($arr)->where($whereStr)->query() == null) {
87 | return false;
88 | } else {
89 | if ($mysql ->cache != null) {
90 | // 缓存删除修改前的数据
91 | $_key = static::$db_name . "_" . "id_cache_" . static::$table . "_" . $id;
92 | unset($mysql ->cache->$_key);
93 | // 缓存存入新的数据
94 | $_key = static::$db_name . "_" . "id_cache_" . static::$table . "_" . $arr ["id"];
95 | $mysql ->cache->$_key = $arr;
96 | }
97 | return true;
98 | }
99 | }
100 |
101 | /**
102 | * 批量删除
103 | */
104 | public static function delete_all($str = "")
105 | {
106 | if ($str=="") {
107 | return;
108 | }
109 | $as = self::all($str);
110 | foreach ($as as $n) {
111 | self::delete($n["id"]);
112 | }
113 | }
114 |
115 | /**
116 | * 删除 传入id删除
117 | */
118 | public static function delete($id = null)
119 | {
120 | $db_name = static::$db_name;
121 | $mysql = ApeWeb::$mysqls[$db_name];
122 |
123 | if ($id == null) {
124 | return false;
125 | }
126 |
127 | // 在缓存中删除
128 | if ($mysql ->cache != null) {
129 | $_key = static::$db_name . "_" . "id_cache_" . static::$table . "_" . $id;
130 | unset($mysql ->cache->$_key);
131 | }
132 |
133 | // 是否使用软删除
134 | if (static::$softDelete) {
135 | $tm = date("Y-m-d H:i:s", time());
136 | $model = self::find($id);
137 | $model [self::$deleted_at] = $tm;
138 | return self::update($model);
139 | }
140 |
141 | // 真删除
142 | $mysql->delete(static::$table)->where("id='$id'")->query();
143 | }
144 |
145 | /**
146 | * 通过id查
147 | */
148 | public static function find($id = null)
149 | {
150 | $db_name = static::$db_name;
151 | $mysql = ApeWeb::$mysqls[$db_name];
152 |
153 | if ($id == null) {
154 | return null;
155 | }
156 | // 如果是$where是数字类型,那么判断缓存中是否有
157 | // 如果有缓存,直接返回缓存值
158 | if ($mysql ->cache != null) {
159 | $_key = static::$db_name . "_" . "id_cache_" . static::$table . "_" . $id;
160 | if (isset($mysql ->cache->$_key)) {
161 | var_export($mysql ->cache->$_key, true);
162 | return $mysql ->cache->$_key;
163 | }
164 | }
165 |
166 | $q = $mysql->select('*')->from(static::$table);
167 | if (static::$softDelete) {
168 | $q->where(self::$deleted_at . " is null");
169 | }
170 | $res = $q->where('id= :id')->bindValues(array('id'=>$id))->row();
171 | if ($res) {
172 | // 将数据存入缓存
173 | if ($mysql ->cache != null) {
174 | $_key = static::$db_name . "_" . "id_cache_" . static::$table . "_" . $id;
175 | $mysql ->cache->$_key = $res;
176 | }
177 | return $res;
178 | } else {
179 | return null;
180 | }
181 | }
182 |
183 | /**
184 | * 查询全部
185 | */
186 | public static function all($where = "1=1", $order = "id desc")
187 | {
188 | $db_name = static::$db_name;
189 | $mysql = ApeWeb::$mysqls[$db_name];
190 | $mysql->query("SELECT * FROM t_admin WHERE id=:id ",array('id' => "1"));
191 | if (static::$softDelete) {
192 | $where = "$where and " . self::$deleted_at . " is null";
193 | }
194 | $arr = $mysql-> ("select * FROM `" . static::$table . "` where $where order by $order");
195 | if ($arr == null) {
196 | return array();
197 | } else {
198 | return $arr;
199 | }
200 | }
201 |
202 | /**
203 | * 查询全部
204 | */
205 | public static function count($where = "1=1")
206 | {
207 | $db_name = static::$db_name;
208 | $mysql = ApeWeb::$mysqls[$db_name];
209 |
210 | if (static::$softDelete) {
211 | $where = "$where and " . self::$deleted_at . " is null";
212 | }
213 | return $mysql->column("select count(*) FROM `" . static::$table . "` where $where") [0];
214 | }
215 |
216 | /**
217 | * 分页查询
218 | */
219 | public static function page($index = 0, $length = 0, $where = " 1=1 ", $order = "id desc")
220 | {
221 | $db_name = static::$db_name;
222 | $mysql = ApeWeb::$mysqls[$db_name];
223 |
224 | if (static::$softDelete) {
225 | $where = "$where and " . self::$deleted_at . " is null";
226 | }
227 |
228 | $cs = $mysql->query("select * FROM `" . static::$table . "` where $where order by $order LIMIT $length OFFSET $index");
229 | $arr ["list"] = $cs;
230 | $allCount = $mysql->column("select count(*) FROM `" . static::$table . "` where $where") [0];
231 | $arr ["all_count"] = $allCount;
232 | if ($length != 0) {
233 | $yu = 0;
234 | if ($allCount > $length) {
235 | if ($allCount % $length > 0) {
236 | $yu = $allCount / $length + 1;
237 | } else {
238 | $yu = $allCount / $length;
239 | }
240 | } else {
241 | $yu = 1;
242 | }
243 | $arr ["all_page_num"] = ( int ) $yu;
244 | } else {
245 | $arr ["all_page_num"] = 1;
246 | }
247 | return $arr;
248 | }
249 |
250 | /**
251 | * 传入正常where串,这个方法会将串分割成预编译模式的sql
252 | */
253 | protected static function getWhereKeyValue($sql){
254 |
255 | }
256 | }
257 |
--------------------------------------------------------------------------------
/_lib/Workerman_linux/Events/Select.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events;
15 |
16 | /**
17 | * select eventloop
18 | */
19 | class Select implements EventInterface
20 | {
21 | /**
22 | * All listeners for read/write event.
23 | *
24 | * @var array
25 | */
26 | public $_allEvents = array();
27 |
28 | /**
29 | * Event listeners of signal.
30 | *
31 | * @var array
32 | */
33 | public $_signalEvents = array();
34 |
35 | /**
36 | * Fds waiting for read event.
37 | *
38 | * @var array
39 | */
40 | protected $_readFds = array();
41 |
42 | /**
43 | * Fds waiting for write event.
44 | *
45 | * @var array
46 | */
47 | protected $_writeFds = array();
48 |
49 | /**
50 | * Timer scheduler.
51 | * {['data':timer_id, 'priority':run_timestamp], ..}
52 | *
53 | * @var \SplPriorityQueue
54 | */
55 | protected $_scheduler = null;
56 |
57 | /**
58 | * All timer event listeners.
59 | * [[func, args, flag, timer_interval], ..]
60 | *
61 | * @var array
62 | */
63 | protected $_task = array();
64 |
65 | /**
66 | * Timer id.
67 | *
68 | * @var int
69 | */
70 | protected $_timerId = 1;
71 |
72 | /**
73 | * Select timeout.
74 | *
75 | * @var int
76 | */
77 | protected $_selectTimeout = 100000000;
78 |
79 | /**
80 | * Paired socket channels
81 | *
82 | * @var array
83 | */
84 | protected $channel = array();
85 |
86 | /**
87 | * Construct.
88 | */
89 | public function __construct()
90 | {
91 | // Create a pipeline and put into the collection of the read to read the descriptor to avoid empty polling.
92 | $this->channel = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
93 | if ($this->channel) {
94 | stream_set_blocking($this->channel[0], 0);
95 | $this->_readFds[0] = $this->channel[0];
96 | }
97 | // Init SplPriorityQueue.
98 | $this->_scheduler = new \SplPriorityQueue();
99 | $this->_scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH);
100 | }
101 |
102 | /**
103 | * {@inheritdoc}
104 | */
105 | public function add($fd, $flag, $func, $args = array())
106 | {
107 | switch ($flag) {
108 | case self::EV_READ:
109 | $fd_key = (int)$fd;
110 | $this->_allEvents[$fd_key][$flag] = array($func, $fd);
111 | $this->_readFds[$fd_key] = $fd;
112 | break;
113 | case self::EV_WRITE:
114 | $fd_key = (int)$fd;
115 | $this->_allEvents[$fd_key][$flag] = array($func, $fd);
116 | $this->_writeFds[$fd_key] = $fd;
117 | break;
118 | case self::EV_SIGNAL:
119 | $fd_key = (int)$fd;
120 | $this->_signalEvents[$fd_key][$flag] = array($func, $fd);
121 | pcntl_signal($fd, array($this, 'signalHandler'));
122 | break;
123 | case self::EV_TIMER:
124 | case self::EV_TIMER_ONCE:
125 | $run_time = microtime(true) + $fd;
126 | $this->_scheduler->insert($this->_timerId, -$run_time);
127 | $this->_task[$this->_timerId] = array($func, (array)$args, $flag, $fd);
128 | $this->tick();
129 | return $this->_timerId++;
130 | }
131 |
132 | return true;
133 | }
134 |
135 | /**
136 | * Signal handler.
137 | *
138 | * @param int $signal
139 | */
140 | public function signalHandler($signal)
141 | {
142 | call_user_func_array($this->_signalEvents[$signal][self::EV_SIGNAL][0], array($signal));
143 | }
144 |
145 | /**
146 | * {@inheritdoc}
147 | */
148 | public function del($fd, $flag)
149 | {
150 | $fd_key = (int)$fd;
151 | switch ($flag) {
152 | case self::EV_READ:
153 | unset($this->_allEvents[$fd_key][$flag], $this->_readFds[$fd_key]);
154 | if (empty($this->_allEvents[$fd_key])) {
155 | unset($this->_allEvents[$fd_key]);
156 | }
157 | return true;
158 | case self::EV_WRITE:
159 | unset($this->_allEvents[$fd_key][$flag], $this->_writeFds[$fd_key]);
160 | if (empty($this->_allEvents[$fd_key])) {
161 | unset($this->_allEvents[$fd_key]);
162 | }
163 | return true;
164 | case self::EV_SIGNAL:
165 | unset($this->_signalEvents[$fd_key]);
166 | pcntl_signal($fd, SIG_IGN);
167 | break;
168 | case self::EV_TIMER:
169 | case self::EV_TIMER_ONCE;
170 | unset($this->_task[$fd_key]);
171 | return true;
172 | }
173 | return false;
174 | }
175 |
176 | /**
177 | * Tick for timer.
178 | *
179 | * @return void
180 | */
181 | protected function tick()
182 | {
183 | while (!$this->_scheduler->isEmpty()) {
184 | $scheduler_data = $this->_scheduler->top();
185 | $timer_id = $scheduler_data['data'];
186 | $next_run_time = -$scheduler_data['priority'];
187 | $time_now = microtime(true);
188 | $this->_selectTimeout = ($next_run_time - $time_now) * 1000000;
189 | if ($this->_selectTimeout <= 0) {
190 | $this->_scheduler->extract();
191 |
192 | if (!isset($this->_task[$timer_id])) {
193 | continue;
194 | }
195 |
196 | // [func, args, flag, timer_interval]
197 | $task_data = $this->_task[$timer_id];
198 | if ($task_data[2] === self::EV_TIMER) {
199 | $next_run_time = $time_now + $task_data[3];
200 | $this->_scheduler->insert($timer_id, -$next_run_time);
201 | }
202 | call_user_func_array($task_data[0], $task_data[1]);
203 | if (isset($this->_task[$timer_id]) && $task_data[2] === self::EV_TIMER_ONCE) {
204 | $this->del($timer_id, self::EV_TIMER_ONCE);
205 | }
206 | continue;
207 | }
208 | return;
209 | }
210 | $this->_selectTimeout = 100000000;
211 | }
212 |
213 | /**
214 | * {@inheritdoc}
215 | */
216 | public function clearAllTimer()
217 | {
218 | $this->_scheduler = new \SplPriorityQueue();
219 | $this->_scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH);
220 | $this->_task = array();
221 | }
222 |
223 | /**
224 | * {@inheritdoc}
225 | */
226 | public function loop()
227 | {
228 | $e = null;
229 | while (1) {
230 | // Calls signal handlers for pending signals
231 | pcntl_signal_dispatch();
232 |
233 | $read = $this->_readFds;
234 | $write = $this->_writeFds;
235 | // Waiting read/write/signal/timeout events.
236 | $ret = @stream_select($read, $write, $e, 0, $this->_selectTimeout);
237 |
238 | if (!$this->_scheduler->isEmpty()) {
239 | $this->tick();
240 | }
241 |
242 | if (!$ret) {
243 | continue;
244 | }
245 |
246 | foreach ($read as $fd) {
247 | $fd_key = (int)$fd;
248 | if (isset($this->_allEvents[$fd_key][self::EV_READ])) {
249 | call_user_func_array($this->_allEvents[$fd_key][self::EV_READ][0],
250 | array($this->_allEvents[$fd_key][self::EV_READ][1]));
251 | }
252 | }
253 |
254 | foreach ($write as $fd) {
255 | $fd_key = (int)$fd;
256 | if (isset($this->_allEvents[$fd_key][self::EV_WRITE])) {
257 | call_user_func_array($this->_allEvents[$fd_key][self::EV_WRITE][0],
258 | array($this->_allEvents[$fd_key][self::EV_WRITE][1]));
259 | }
260 | }
261 | }
262 | }
263 |
264 | /**
265 | * Destroy loop.
266 | *
267 | * @return void
268 | */
269 | public function destroy()
270 | {
271 |
272 | }
273 | }
274 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Events/React.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events;
15 | use React\EventLoop\LoopInterface;
16 | use React\EventLoop\Timer\TimerInterface;
17 |
18 | /**
19 | * select eventloop
20 | */
21 | class React implements LoopInterface
22 | {
23 | /**
24 | * @var React\EventLoop\LoopInterface
25 | */
26 | protected $_loop = null;
27 |
28 | /**
29 | * @var array
30 | */
31 | protected $_timerIdMap = array();
32 |
33 | /**
34 | * @var int
35 | */
36 | protected $_timerIdIndex = 0;
37 |
38 | /**
39 | * React constructor.
40 | */
41 | public function __construct() {
42 | if (function_exists('event_base_new')) {
43 | $this->_loop = new \Workerman\Events\React\LibEventLoop();
44 | } elseif (class_exists('EventBase', false)) {
45 | $this->_loop = new \Workerman\Events\React\ExtEventLoop();
46 | } else {
47 | $this->_loop = new \Workerman\Events\React\StreamSelectLoop();
48 | }
49 | }
50 |
51 | /**
52 | * Add event listener to event loop.
53 | *
54 | * @param $fd
55 | * @param $flag
56 | * @param $func
57 | * @param array $args
58 | * @return bool
59 | */
60 | public function add($fd, $flag, $func, $args = array())
61 | {
62 | $args = (array)$args;
63 | switch ($flag) {
64 | case EventInterface::EV_READ:
65 | return $this->_loop->addReadStream($fd, $func);
66 | case EventInterface::EV_WRITE:
67 | return $this->_loop->addWriteStream($fd, $func);
68 | case EventInterface::EV_SIGNAL:
69 | return $this->_loop->addSignal($fd, $func);
70 | case EventInterface::EV_TIMER:
71 | $timer_obj = $this->_loop->addPeriodicTimer($fd, function() use ($func, $args) {
72 | call_user_func_array($func, $args);
73 | });
74 | $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
75 | return $this->_timerIdIndex;
76 | case EventInterface::EV_TIMER_ONCE:
77 | $timer_obj = $this->_loop->addTimer($fd, function() use ($func, $args) {
78 | call_user_func_array($func, $args);
79 | });
80 | $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
81 | return $this->_timerIdIndex;
82 | }
83 | return false;
84 | }
85 |
86 | /**
87 | * Remove event listener from event loop.
88 | *
89 | * @param mixed $fd
90 | * @param int $flag
91 | * @return bool
92 | */
93 | public function del($fd, $flag)
94 | {
95 | switch ($flag) {
96 | case EventInterface::EV_READ:
97 | return $this->_loop->removeReadStream($fd);
98 | case EventInterface::EV_WRITE:
99 | return $this->_loop->removeWriteStream($fd);
100 | case EventInterface::EV_SIGNAL:
101 | return $this->_loop->removeSignal($fd);
102 | case EventInterface::EV_TIMER:
103 | case EventInterface::EV_TIMER_ONCE;
104 | if (isset($this->_timerIdMap[$fd])){
105 | $timer_obj = $this->_timerIdMap[$fd];
106 | unset($this->_timerIdMap[$fd]);
107 | $this->_loop->cancelTimer($timer_obj);
108 | return true;
109 | }
110 | }
111 | return false;
112 | }
113 |
114 |
115 | /**
116 | * Main loop.
117 | *
118 | * @return void
119 | */
120 | public function loop()
121 | {
122 | $this->_loop->run();
123 | }
124 |
125 | /**
126 | * Register a listener to be notified when a stream is ready to read.
127 | *
128 | * @param resource $stream The PHP stream resource to check.
129 | * @param callable $listener Invoked when the stream is ready.
130 | */
131 | public function addReadStream($stream, callable $listener) {
132 | return call_user_func(array($this->_loop, 'addReadStream'), $stream, $listener);
133 | }
134 |
135 | /**
136 | * Register a listener to be notified when a stream is ready to write.
137 | *
138 | * @param resource $stream The PHP stream resource to check.
139 | * @param callable $listener Invoked when the stream is ready.
140 | */
141 | public function addWriteStream($stream, callable $listener) {
142 | return call_user_func(array($this->_loop, 'addWriteStream'), $stream, $listener);
143 | }
144 |
145 | /**
146 | * Remove the read event listener for the given stream.
147 | *
148 | * @param resource $stream The PHP stream resource.
149 | */
150 | public function removeReadStream($stream) {
151 | return call_user_func(array($this->_loop, 'removeReadStream'), $stream);
152 | }
153 |
154 | /**
155 | * Remove the write event listener for the given stream.
156 | *
157 | * @param resource $stream The PHP stream resource.
158 | */
159 | public function removeWriteStream($stream) {
160 | return call_user_func(array($this->_loop, 'removeWriteStream'), $stream);
161 | }
162 |
163 | /**
164 | * Remove all listeners for the given stream.
165 | *
166 | * @param resource $stream The PHP stream resource.
167 | */
168 | public function removeStream($stream) {
169 | return call_user_func(array($this->_loop, 'removeStream'), $stream);
170 | }
171 |
172 | /**
173 | * Enqueue a callback to be invoked once after the given interval.
174 | *
175 | * The execution order of timers scheduled to execute at the same time is
176 | * not guaranteed.
177 | *
178 | * @param int|float $interval The number of seconds to wait before execution.
179 | * @param callable $callback The callback to invoke.
180 | *
181 | * @return TimerInterface
182 | */
183 | public function addTimer($interval, callable $callback) {
184 | return call_user_func(array($this->_loop, 'addTimer'), $interval, $callback);
185 | }
186 |
187 | /**
188 | * Enqueue a callback to be invoked repeatedly after the given interval.
189 | *
190 | * The execution order of timers scheduled to execute at the same time is
191 | * not guaranteed.
192 | *
193 | * @param int|float $interval The number of seconds to wait before execution.
194 | * @param callable $callback The callback to invoke.
195 | *
196 | * @return TimerInterface
197 | */
198 | public function addPeriodicTimer($interval, callable $callback) {
199 | return call_user_func(array($this->_loop, 'addPeriodicTimer'), $interval, $callback);
200 | }
201 |
202 | /**
203 | * Cancel a pending timer.
204 | *
205 | * @param TimerInterface $timer The timer to cancel.
206 | */
207 | public function cancelTimer(TimerInterface $timer) {
208 | return call_user_func(array($this->_loop, 'cancelTimer'), $timer);
209 | }
210 |
211 | /**
212 | * Check if a given timer is active.
213 | *
214 | * @param TimerInterface $timer The timer to check.
215 | *
216 | * @return boolean True if the timer is still enqueued for execution.
217 | */
218 | public function isTimerActive(TimerInterface $timer) {
219 | return call_user_func(array($this->_loop, 'isTimerActive'), $timer);
220 | }
221 |
222 | /**
223 | * Schedule a callback to be invoked on the next tick of the event loop.
224 | *
225 | * Callbacks are guaranteed to be executed in the order they are enqueued,
226 | * before any timer or stream events.
227 | *
228 | * @param callable $listener The callback to invoke.
229 | */
230 | public function nextTick(callable $listener) {
231 | return call_user_func(array($this->_loop, 'nextTick'), $listener);
232 | }
233 |
234 | /**
235 | * Schedule a callback to be invoked on a future tick of the event loop.
236 | *
237 | * Callbacks are guaranteed to be executed in the order they are enqueued.
238 | *
239 | * @param callable $listener The callback to invoke.
240 | */
241 | public function futureTick(callable $listener) {
242 | return call_user_func(array($this->_loop, 'futureTick'), $listener);
243 | }
244 |
245 | /**
246 | * Perform a single iteration of the event loop.
247 | */
248 | public function tick() {
249 | return call_user_func(array($this->_loop, 'tick'));
250 | }
251 |
252 | /**
253 | * Run the event loop until there are no more tasks to perform.
254 | */
255 | public function run() {
256 | return call_user_func(array($this->_loop, 'run'));
257 | }
258 |
259 | /**
260 | * Instruct a running event loop to stop.
261 | */
262 | public function stop() {
263 | return call_user_func(array($this->_loop, 'stop'));
264 | }
265 | }
266 |
--------------------------------------------------------------------------------
/_lib/ape/ApeWeb.php:
--------------------------------------------------------------------------------
1 | _sendfile = new Sendfile();
35 | $this->_sendfile->useETag = true;
36 | $this->_sendfile->cacheControl = true;
37 | $this->_sendfile->use304status = true;
38 | // 默认session为null
39 | $_SESSION = null;
40 | parent::__construct($socket_name, $context_option);
41 | }
42 |
43 | /**
44 | * 添加拦截器
45 | */
46 | public function AddFilter($url, callable $callback)
47 | {
48 | if (is_callable($callback)) {
49 | if ($callback instanceof \Closure) {
50 | $callback = \Closure::bind($callback, $this, get_class());
51 | }
52 | } else {
53 | throw new \Exception('can not HandleFunc');
54 | }
55 | $this->map [] = array(
56 | $url,
57 | $callback
58 | );
59 | }
60 |
61 | /**
62 | * 发送404
63 | *
64 | * @param unknown $connection
65 | */
66 | private function send_404($connection)
67 | {
68 | if ($this->on404) {
69 | $callback = \Closure::bind($this->on404, $this, get_class());
70 | call_user_func($callback);
71 | } else {
72 | Http::header("HTTP/1.1 404 Not Found");
73 | $html = 'page not found';
74 | $connection->send($html);
75 | }
76 | }
77 |
78 | /**
79 | * 每次发送请求完,自动关闭连接
80 | */
81 | private function auto_close(&$conn, &$static = false)
82 | {
83 | /**
84 | * 如果不是访问静态
85 | * 如果启用session了,还没有关闭,在这里关闭
86 | */
87 | if (! $static) {
88 | if (HttpCache::$instance->sessionStarted) {
89 | HttpCache::$instance->sessionStarted = false;
90 | Http::sessionWriteClose();
91 | }
92 | //$conn->close ();
93 | if (strtolower($_SERVER ["SERVER_PROTOCOL"]) == "http/1.1") {
94 | if (isset($_SERVER ["HTTP_CONNECTION"])) {
95 | if (strtolower($_SERVER ["HTTP_CONNECTION"]) == "close") {
96 | $conn->close();
97 | }
98 | }
99 | } else {
100 | if ($_SERVER ["HTTP_CONNECTION"] != "keep-alive") {
101 | $conn->close();
102 | }
103 | }
104 | }
105 | // 在这里自定义一些统计
106 | $this->access_log [7] = time() - $this->access_log [7];
107 | // 向UDP日志服务发送日志数据
108 | dd_log(implode(" - ", $this->access_log), "request");
109 | }
110 |
111 | /**
112 | * 当有静态文件访问时
113 | */
114 | public function onStaticFile($connection, $data)
115 | {
116 | $uri = $data ["server"] ["REQUEST_URI"];
117 | $pos = stripos($uri, "?");
118 | if ($pos != false) {
119 | $uri = substr($uri, 0, $pos);
120 | }
121 |
122 | $file = RUN_DIR . 'public/' . $uri;
123 | $path = realpath($file);
124 | // 如果没有这个文件
125 | if (! $path) {
126 | Http::header('HTTP/1.1 400 Bad Request');
127 | $connection->send('400 Bad Request
');
128 | return;
129 | }
130 | // 只允许访问public文件夹下面
131 | if (strpos($path, RUN_DIR . 'public/') != 0) {
132 | Http::header('HTTP/1.1 400 Bad Request');
133 | $connection->send('400 Bad Request
');
134 | return;
135 | }
136 | Sendfile::sendFile($connection, $path);
137 | }
138 |
139 | /**
140 | * 获取客户端消息
141 | */
142 | public function onMessage($connection, $data)
143 | {
144 | ApeWeb::$HOME = "http://".$_SERVER['HTTP_HOST']."/";
145 | // 初始化SEND_BODY
146 | ApeWeb::$SEND_BODY = "";
147 | $this->access_log [0] = $_SERVER ["REMOTE_ADDR"];
148 | $this->access_log [1] = T(time());
149 | $this->access_log [2] = $_SERVER ['REQUEST_METHOD'];
150 | $this->access_log [3] = $_SERVER ['REQUEST_URI'];
151 | $this->access_log [4] = $_SERVER ['SERVER_PROTOCOL'];
152 | $this->access_log [5] = "NULL";
153 | $this->access_log [6] = 200;
154 | $this->access_log [7] = time();
155 | //这块的作用是,如果访问的是/,默认增加模块
156 | // if ($data ["server"] ["REQUEST_URI"]=="/") {
157 | // $data ["server"] ["REQUEST_URI"] = $data ["server"] ["REQUEST_URI"] . APE['config'] ["default_module"];
158 | // $_SERVER ['REQUEST_URI'] = $_SERVER ['REQUEST_URI'] . APE['config'] ["default_module"];
159 | // }
160 | // 网站根目录
161 | $url = $data ["server"] ["REQUEST_URI"];
162 | $pos = stripos($url, "?");
163 | if ($pos != false) {
164 | $url = substr($url, 0, $pos);
165 | }
166 | if ($url != "/") {
167 | $url = strtolower(trim($url, "/"));
168 | }
169 | $data ["server"] ["REQUEST_URL"] = $url;
170 | $this->conn = $connection;
171 |
172 | if ($url == "/") {
173 | $url_arr = array();
174 | } else {
175 | $url_arr = explode("/", $url);
176 | }
177 | $success = false;
178 | $static = false;
179 | // 如果是访问静态文件
180 | if (count($url_arr) > 0 && strpos($url_arr [(count($url_arr) - 1)], '.') != false) {
181 | $this->onStaticFile($connection, $data);
182 | $success = true;
183 | $static = true;
184 | } else {
185 | // 如果是访问controller,通过路由匹配控制器和方法
186 | $r_call = Router::router($data, $this->map, $this->access_log, $module_name, $controller_path, $controller_name, $method_name);
187 | // 如果通过拦截器检查
188 | if ($r_call) {
189 | $c_u_f_path = $module_name . $controller_path . $controller_name. "Controller";
190 | $c_u_f_path = str_replace(DS, '\\', $c_u_f_path);
191 |
192 | //将-符号改为_ , 因为PHP方法名字不支持-
193 | $c_u_f_path = str_replace("-", '_', $c_u_f_path);
194 | $method_name = str_replace("-", '_', $method_name);
195 |
196 | // 寻找controller,并且验证是否类中包含指定方法,找到就执行方法
197 | if (is_file(RUN_DIR.$module_name . $controller_path . $controller_name . "Controller.php")
198 | &&method_exists('\\'.$c_u_f_path, $method_name)) {
199 | $success = true;
200 | //将方法名字拼接上
201 | $c_u_f_path = $c_u_f_path . "::" . $method_name;
202 | $f_call = null;
203 | try {
204 | $f_call = call_user_func($c_u_f_path, $this, $data);
205 | } catch (\Exception $e) {
206 | var_dump($e->getMessage());
207 | }
208 |
209 | // 直接发送他的返回值
210 | if ($f_call !== null || ApeWeb::$SEND_BODY != "") {
211 | if (is_bool($f_call)) {
212 | $f_call = "";
213 | }
214 | if (ApeWeb::$SEND_BODY != "") {
215 | $f_call = ApeWeb::$SEND_BODY . $f_call;
216 | }
217 | $this->send($f_call);
218 | }
219 | }
220 | } else {
221 | // 拦截器检查没通过,不报404,拦截器自己处理
222 | $success = true;
223 | $this->send(ApeWeb::$SEND_BODY);
224 | }
225 | }
226 |
227 | if (! $success) {
228 | // 没找到路由,直接404错误
229 | $this->send_404($connection);
230 | }
231 | // 每次发送完消息,自动关闭连接
232 | $this->auto_close($connection, $static);
233 |
234 | // 已经处理请求数
235 | static $request_count = 0;
236 | // 如果请求数达到max_request
237 | if (++ $request_count >= APE['config']["max_request"] && APE['config']["max_request"] > 0) {
238 | Worker::stopAll();
239 | }
240 | }
241 |
242 | /**
243 | * 发送文本
244 | *
245 | * @param unknown $data
246 | */
247 | public function send($data)
248 | {
249 | $this->conn->send($data);
250 | }
251 |
252 | /**
253 | * worker进程启动
254 | */
255 | public function run()
256 | {
257 | // 设置当前worker是否开启监听端口复用(socket的SO_REUSEPORT选项),默认为false,不开启。
258 | $this->reusePort = false;
259 | $this->onWorkerStart = $this->onStart;
260 |
261 | // 一个已实例化的 object 的方法被作为 array 传递,
262 | // 下标 0 包含该 object,下标 1 包含方法名。 在同一个类里可以访问 protected 和 private 方法。
263 | $this->onMessage = array(
264 | $this,
265 | 'onMessage'
266 | );
267 | parent::run();
268 | }
269 | }
270 |
--------------------------------------------------------------------------------
/_lib/Workerman_win/Events/Select.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright walkor
11 | * @link http://www.workerman.net/
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
13 | */
14 | namespace Workerman\Events;
15 |
16 | class Select implements EventInterface
17 | {
18 | /**
19 | * 所有的事件
20 | * @var array
21 | */
22 | public $_allEvents = array();
23 |
24 | /**
25 | * 所有信号事件
26 | * @var array
27 | */
28 | public $_signalEvents = array();
29 |
30 | /**
31 | * 监听这些描述符的读事件
32 | * @var array
33 | */
34 | protected $_readFds = array();
35 |
36 | /**
37 | * 监听这些描述符的写事件
38 | * @var array
39 | */
40 | protected $_writeFds = array();
41 |
42 | /**
43 | * 监听这些描述符的带外事件
44 | * @var array
45 | */
46 | protected $_exceptFds = array();
47 |
48 | /**
49 | * 任务调度器,最大堆
50 | * {['data':timer_id, 'priority':run_timestamp], ..}
51 | * @var SplPriorityQueue
52 | */
53 | protected $_scheduler = null;
54 |
55 | /**
56 | * 定时任务
57 | * [[func, args, flag, timer_interval], ..]
58 | * @var array
59 | */
60 | protected $_task = array();
61 |
62 | /**
63 | * 定时器id
64 | * @var int
65 | */
66 | protected $_timerId = 1;
67 |
68 | /**
69 | * select超时时间,单位:微秒
70 | * @var int
71 | */
72 | protected $_selectTimeout = 100000000;
73 |
74 | /**
75 | * 构造函数
76 | * @return void
77 | */
78 | public function __construct()
79 | {
80 | // 创建一个管道,放入监听读的描述符集合中,避免空轮询
81 | $this->channel = stream_socket_pair(STREAM_PF_INET, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
82 | if($this->channel)
83 | {
84 | stream_set_blocking($this->channel[0], 0);
85 | $this->_readFds[0] = $this->channel[0];
86 | }
87 | // 初始化优先队列(最大堆)
88 | $this->_scheduler = new \SplPriorityQueue();
89 | $this->_scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH);
90 | }
91 |
92 | /**
93 | * 添加事件及处理函数
94 | * @see Events\EventInterface::add()
95 | */
96 | public function add($fd, $flag, $func, $args = array())
97 | {
98 | switch ($flag)
99 | {
100 | case self::EV_READ:
101 | $fd_key = (int)$fd;
102 | $this->_allEvents[$fd_key][$flag] = array($func, $fd);
103 | $this->_readFds[$fd_key] = $fd;
104 | break;
105 | case self::EV_WRITE:
106 | $fd_key = (int)$fd;
107 | $this->_allEvents[$fd_key][$flag] = array($func, $fd);
108 | $this->_writeFds[$fd_key] = $fd;
109 | break;
110 | case self::EV_EXCEPT:
111 | $fd_key = (int)$fd;
112 | $this->_allEvents[$fd_key][$flag] = array($func, $fd);
113 | $this->_exceptFds[$fd_key] = $fd;
114 | break;
115 | case self::EV_SIGNAL:
116 | throw new \Exception("not support EV_SIGNAL on Windows");
117 | break;
118 | case self::EV_TIMER:
119 | case self::EV_TIMER_ONCE:
120 | // $fd 为 定时的时间间隔,单位为秒,支持小数,能精确到0.001秒
121 | $run_time = microtime(true)+$fd;
122 | $this->_scheduler->insert($this->_timerId, -$run_time);
123 | $this->_task[$this->_timerId] = array($func, (array)$args, $flag, $fd);
124 | $this->tick();
125 | return $this->_timerId++;
126 | }
127 |
128 | return true;
129 | }
130 |
131 | /**
132 | * 信号处理函数
133 | * @param int $signal
134 | */
135 | public function signalHandler($signal)
136 | {
137 | call_user_func_array($this->_signalEvents[$signal][self::EV_SIGNAL][0], array($signal));
138 | }
139 |
140 | /**
141 | * 删除某个描述符的某类事件的监听
142 | * @see Events\EventInterface::del()
143 | */
144 | public function del($fd ,$flag)
145 | {
146 | $fd_key = (int)$fd;
147 | switch ($flag)
148 | {
149 | case self::EV_READ:
150 | unset($this->_allEvents[$fd_key][$flag], $this->_readFds[$fd_key]);
151 | if(empty($this->_allEvents[$fd_key]))
152 | {
153 | unset($this->_allEvents[$fd_key]);
154 | }
155 | return true;
156 | case self::EV_WRITE:
157 | unset($this->_allEvents[$fd_key][$flag], $this->_writeFds[$fd_key]);
158 | if(empty($this->_allEvents[$fd_key]))
159 | {
160 | unset($this->_allEvents[$fd_key]);
161 | }
162 | return true;
163 | case self::EV_EXCEPT:
164 | unset($this->_allEvents[$fd_key][$flag], $this->_exceptFds[$fd_key]);
165 | if(empty($this->_allEvents[$fd_key]))
166 | {
167 | unset($this->_allEvents[$fd_key]);
168 | }
169 | return true;
170 | case self::EV_SIGNAL:
171 | break;
172 | case self::EV_TIMER:
173 | case self::EV_TIMER_ONCE;
174 | // $fd_key为要删除的定时器id,即timerId
175 | unset($this->_task[$fd_key]);
176 | return true;
177 | }
178 | return false;;
179 | }
180 |
181 | /**
182 | * 检查是否有可执行的定时任务,有的话执行
183 | * @return void
184 | */
185 | protected function tick()
186 | {
187 | while(!$this->_scheduler->isEmpty())
188 | {
189 | $scheduler_data = $this->_scheduler->top();
190 | $timer_id = $scheduler_data['data'];
191 | $next_run_time = -$scheduler_data['priority'];
192 | $time_now = microtime(true);
193 | $this->_selectTimeout = ($next_run_time - $time_now) * 1000000;
194 | if ($this->_selectTimeout <= 0) {
195 | $this->_scheduler->extract();
196 | if (!isset($this->_task[$timer_id])) {
197 | continue;
198 | }
199 | // [func, args, flag, timer_interval]
200 | $task_data = $this->_task[$timer_id];
201 | if ($task_data[2] === self::EV_TIMER) {
202 | $next_run_time = $time_now + $task_data[3];
203 | $this->_scheduler->insert($timer_id, -$next_run_time);
204 | }
205 | call_user_func_array($task_data[0], $task_data[1]);
206 | if (isset($this->_task[$timer_id]) && $task_data[2] === self::EV_TIMER_ONCE) {
207 | $this->del($timer_id, self::EV_TIMER_ONCE);
208 | }
209 | continue;
210 | }
211 | return;
212 | }
213 | $this->_selectTimeout = 100000000;
214 | }
215 |
216 | /**
217 | * 删除所有定时器
218 | * @return void
219 | */
220 | public function clearAllTimer()
221 | {
222 | $this->_scheduler = new \SplPriorityQueue();
223 | $this->_scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH);
224 | $this->_task = array();
225 | }
226 |
227 | /**
228 | * 主循环
229 | * @see Events\EventInterface::loop()
230 | */
231 | public function loop()
232 | {
233 | $e = null;
234 | while (1)
235 | {
236 | $read = $this->_readFds;
237 | $write = $this->_writeFds;
238 | $except = $this->_writeFds;
239 |
240 | // 等待可读或者可写事件
241 | stream_select($read, $write, $except, 0, (int)($this->_selectTimeout.''));
242 |
243 | // 尝试执行定时任务
244 | if(!$this->_scheduler->isEmpty())
245 | {
246 | $this->tick();
247 | }
248 |
249 | // 这些描述符可读,执行对应描述符的读回调函数
250 | if($read)
251 | {
252 | foreach($read as $fd)
253 | {
254 | $fd_key = (int) $fd;
255 | if(isset($this->_allEvents[$fd_key][self::EV_READ]))
256 | {
257 | call_user_func_array($this->_allEvents[$fd_key][self::EV_READ][0], array($this->_allEvents[$fd_key][self::EV_READ][1]));
258 | }
259 | }
260 | }
261 |
262 | // 这些描述符可写,执行对应描述符的写回调函数
263 | if($write)
264 | {
265 | foreach($write as $fd)
266 | {
267 | $fd_key = (int) $fd;
268 | if(isset($this->_allEvents[$fd_key][self::EV_WRITE]))
269 | {
270 | call_user_func_array($this->_allEvents[$fd_key][self::EV_WRITE][0], array($this->_allEvents[$fd_key][self::EV_WRITE][1]));
271 | }
272 | }
273 | }
274 |
275 | // 这些描述符可写,执行对应描述符的写回调函数
276 | if($except)
277 | {
278 | foreach($except as $fd)
279 | {
280 | $fd_key = (int) $fd;
281 | if(isset($this->_allEvents[$fd_key][self::EV_EXCEPT]))
282 | {
283 | call_user_func_array($this->_allEvents[$fd_key][self::EV_EXCEPT][0], array($this->_allEvents[$fd_key][self::EV_EXCEPT][1]));
284 | }
285 | }
286 | }
287 | }
288 | }
289 | }
290 |
--------------------------------------------------------------------------------