安装使用swoole
swoole首页:https://www.swoole.com/
方法1:使用pecl安装
pecl install swoole
注意,php版本必须是7.0以及7.0以上的版本。
方法2:编译源码安装
第一步:下载swoole的源码
下载源码的时候要注意,swoole2.0及以后版本不再支持PHP5.x
git clone https://github.com/swoole/swoole-src.git
第二步:进入源码目录,执行phpize命令
第三步:配置php-config的路径
./configure --with-php-config=/usr/local/php/bin/php-config
第四步:将php.ini中被禁止的proc_open、proc_get_status、system、exec、shell_exec这几个函数从其中删除,因为在make时要用到这几个函数。
第五步:make
注意:如果下载的swoole 2.x,而php版本低于7.0,在这一步会失败,请下载正确源码版本
第六步:make test
第七步检测是否安装成功
php -m
使用swoole搭建一个http服务器
<?php $http = new swoole_http_server("0.0.0.0",9501); $http->on("request", function($request, $response){ print_r($request); print_r($response); }); $http->start();
向服务器发起请求:
curl 123.123.123.123:9501/aaa/bbb/index.html
运行结果:
Swoole\Http\Request Object ( [fd] => 1 [header] => Array ( [user-agent] => curl/7.29.0 [host] => 123.123.123.123:9501 [accept] => */* ) [server] => Array ( [request_method] => GET [request_uri] => /aaa/bbb/index.html [path_info] => /aaa/bbb/index.html [request_time] => 1531286716 [request_time_float] => 1531286716.3838 [server_port] => 9501 [remote_port] => 46576 [remote_addr] => 123.123.123.123 [master_time] => 1531286716 [server_protocol] => HTTP/1.1 [server_software] => swoole-http-server ) [request] => [cookie] => [get] => [files] => [post] => [tmpfiles] => ) Swoole\Http\Response Object ( [fd] => 1 [header] => [cookie] => [trailer] => )
可以观察一下上面Swoole\Http\Request和Swoole\Http\Response的结构(属性)。
使用http服务器返回数据
<?php $http = new swoole_http_server("0.0.0.0",9501); $http->on("request", function($request, $response){ $response->header("Content-Type","text/html;chatset=utf-8"); $response->end("hello world\n"); }); $http->start();
运行脚本,然后请求服务器:
[root@centos ~]# curl xxx.xxx.xxx.xxx:9501/aaa/bbb/index.html hello world
创建WebSocket服务器
显示index.html的websocket客户端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body></body> <script> let ws = new WebSocket("ws://ganlixin.cn:9501"); ws.onopen = function(){ console.log("connect success"); } ws.onclose = function(){ console.log("closed") } ws.onmessage = function(res){ console.log(res.data) } </script> </html>
websocket服务器:
<?php $ws = new swoole_websocket_server("0.0.0.0",9501); //打开连接 $ws->on("open", function($serv, $request){ echo "connected \n"; //向客户端发送信息 $serv->push($request->fd, "hello world\n"); }); //接收到数据 $ws->on("message", function($serv, $request){ echo "received data\n"; $serv->push($request->fd, "get message from client : {$request->data}"); }); //关闭连接 $ws->on("close", function(){ echo "closed\n"; }); $ws->start();
运行index.html,看控制台,有信息输出:
定时器
面向过程的形式
<?php //循环定时器 //int swoole_timer_tick(int $ms, callable $callback, mixed $user_param); $timer_id = swoole_timer_tick(5000, function($timer_id) { echo "current time " . date("Y-m-d H:i:s",time()) . "\n"; }); echo $timer_id; //清除定时器 //swoole_timer_clear($timer_id);
面向对象的形式
<?php //循环定时器 $server = new swoole_server("0.0.0.0", 9501); $timer_id = $server->tick(1000,function($timer_id){ echo "timer_id : " . $timer_id . " current time " . date("Y-m-d H:i:s",time()) . "\n"; }); //注意,没有$swoole_server->clear(); swoole_timer_clear($timer_id);
使用定时器,一般都是使用面向过程的形式,因为那样的话,可以不用指定ip以及port。
异步TCP服务器
<?php //创建TCP服务器,默认是同步阻塞工作模式 $server = new swoole_server("0.0.0.0",9501); //设置异步进程数量 $server->set( [ "task_worker_num" => 4 ]); //接收到请求时 $server->on("receive", function($serv, $data, $fd){ $task_id = $serv->task($data); //生成异步任务id echo "task id is " . $task_id . "\n"; }); //处理异步任务 $server->on("task", function($serv, $task_id, $from_id, $data){ echo "执行异步任务 task_id : $task_id \n"; $serv->finish("data -> OK"); }); $server->on("finish", function($serv, $task_id, $data){ echo "执行任务{$task_id}完成\n"; }); $server->start(); ?>
多次访问服务器绑定的端口,会看到服务器控制台输出内容如下
[root@centos index]# php index.php task id is 0 执行异步任务 task_id : 0 执行任务0完成 task id is 1 执行异步任务 task_id : 1 执行任务1完成 task id is 2 执行异步任务 task_id : 2 执行任务2完成 task id is 3 执行异步任务 task_id : 3 执行任务3完成
TCP客户端
<?php //创建tcp客户端 //swoole_client->__construct(int $sock_type, int $is_sync = SWOOLE_SOCK_SYNC, string $key); $client = new swoole_client(SWOOLE_SOCK_TCP); //连接服务器 //bool $swoole_client->connect(string $host, int $port, float $timeout = 0.5, int $flag = 0) $client->connect("123.123.123.123", 9501, 5) or die("连接失败"); //发送数据request //int $swoole_client->send(string $data); $client->send("hello world"); //接受服务器的response //string $swoole_client->recv(int $size = 65535, int $flags = 0); //第二个参数表示是否等到所有数据都到达之后再返回 $res = $client->recv(65535); echo $res;
异步TCP客户端
<?php //创建一个异步tcp客户端 $client = new swoole_client(SWOOLE_SOCK_TCP,SWOOLE_SOCK_ASYNC); //只有tcp客户端是异步的时候,可以绑定事件 $client->on("connect", function($cli){ echo "connect\n"; }); $client->on("receive", function($cli, $data){ echo "data : $data \n"; }); $client->on("err", function($cli){ echo "error\n"; }); $client->on("close", function($cli){ echo "closed\n"; }); $client->connect("ganlixin.cn",80,10); ?>
创建进程执行指定任务
<?php //创建一个函数,包含之后创建的进程要干的任务 function doJob(swoole_process $worker){ /* print_r($worker); Swoole\Process Object ( [pipe] => 5 [callback] => doJob [msgQueueId] => [msgQueueKey] => [pid] => 22777 [id] => ) */ //执行外部程序 //bool swoole_process->exec(string $execfile, array $args) $worker->exec('/usr/local/apache/bin/apachectl',array("start")); } //创建进程,将要做的事情(上面指定的函数)传递给构造方法 $process_1 = new swoole_process("doJob"); $pid = $process_1->start(); //echo $pid,"\n"; $process_2 = new swoole_process("doJob"); $pid = $process_2->start(); //echo $pid,"\n"; //等待进程结束 swoole_process::wait();
指定进程事件
<?php //进程池 $process_pool = array(); //进程数量 $process_num = 4; //创建任务 function doJob(swoole_process $process){ //向管道中写入自己的pid $process->write("my pid is $process->pid"); echo "pid : $process->pid 已写入信息\n"; $process->callback; } for ( $i = 0; $i < $process_num; $i++ ) { $process = new swoole_process("doJob"); $pid = $process->start(); $process_pool[] = $process; //存入进程池 } //向每一个子进程指定需要执行的操作 foreach($process_pool as $process){ swoole_event_add($process->pipe, function($pipe) use ($process){ $data = $process->read(); echo "接收到数据 $data\n"; }); }
运行:
pid : 25176 已写入信息 接收到数据 my pid is 25176 pid : 25177 已写入信息 接收到数据 my pid is 25177 pid : 25175 已写入信息 接收到数据 my pid is 25175 pid : 25174 已写入信息 接收到数据 my pid is 25174
进程队列
<?php //进程池 $process_pool = array(); //进程数 $process_num = 4; //子进程要执行的任务 function doJob(swoole_process $process){ $recv_data = $process->pop();//默认8192字节 echo "从主进程收到数据 $recv_data\n"; sleep(1); $process->exit(0);//进程退出 } for ( $i = 0; $i < $process_num; $i++ ) { $process = new swoole_process("doJob",false,false); //加入进程池 $process_pool[] = $process; $process->useQueue();//开启进程队列 $process->start(); } //主进程执行 foreach($process_pool as $process){ //主进程向子进程发送数据 $process->push("hello, I'm your father, your pid is $process->pid\n"); } //等待子进程结束 for ( $i = 0; $i < $process_num; $i++ ) { //array swoole_process::wait(bool $blocking = true); $process = swoole_process::wait(); echo "子进程{$process["pid"]}退出\n"; } //销毁进程池 unset($process_pool); ?>
信号触发
<?php swoole_process::signal(SIGALRM,function(){ //每次收到SIGALRM信号就执行一次 echo "one"; /* 满足某种条件是,取消定时触发信号 if ( condition ){ swoole_process::alarm(-1); } */ }); //单位是微秒 1秒=1000000微秒 //一秒触发一次alarm信号 swoole_process::alarm(1000000); //上面的代码等同于 //swoole_timer_tick(1000,function(){ // echo "one"; //});
互斥锁
<?php //创建互斥锁 $mutex = new swoole_lock(SWOOLE_MUTEX); $mutex->lock(); echo "父进程加锁\n"; if ( pcntl_fork() > 0){ //主进程执行 sleep(2); $mutex->unlock(); } else { //子进程执行 echo "子进程等待父进程解锁\n"; $mutex->lock(); echo "子进程加锁\n"; $mutex->unlock(); exit("子进程退出\n"); } echo "主进程释放锁\n"; unset($mutex); ?>
运行结果:
[root@centos index]# php mutex.php 父进程加锁 子进程等待父进程解锁 主进程释放锁 子进程加锁 子进程退出
DNS查询
通过传入域名,返回ip。
<?php swoole_async_dns_lookup("www.swoole.com", function($host, $ip){ echo "{$host} : {$ip}\n"; }); ?>
异步读取文件
在PHP中读取文件,如果是大文件,可能需要的时间就长一点,那么就要修改php配置参数。
<?php //采取分段读的方式 //bool swoole_async_read(string $filename, mixed $callback, int $size = 8192, int $offset = 0); swoole_async_read("./mutex.php", function($filename,$content){ echo $content; },10);
异步读取文件
分段写入
<?php $content = file_get_contents("beego.tar"); //分段写入 //swoole_async_write(string $filename, string $content, int $offset = -1, mixed $callback = NULL); //offset置为-1时,表示追加方式 swoole_async_write("data.tar", $content,1);
异步mysql
<?php $mysql = new swoole_mysql(); $config = array( "host" => "localhost", "user" => "root", "password" => "123456", "database" => "test", "charset" => "utf8" ); $mysql->connect($config, function(swoole_mysql $db, $result){ if ($result === FALSE) { echo "$result->connect_errno , $result->connect_error\n"; exit(); } echo "数据库连接成功\n"; $sql = "select * from demo"; $db->query($sql, function($link, $result){ if ($result === FALSE) { echo "执行SQL失败\n"; exit(); } print_r($result); //$result保存着结果集 }); }); ?>
运行:
[root@centos index]# php async_mysql.php 数据库连接成功 Array ( [0] => Array ( [id] => 1 [name] => aaa [age] => 10 ) [1] => Array ( [id] => 2 [name] => bbb [age] => 20 ) )
如需转载,请注明文章出处,谢谢!!!