pecl install swoolephp
注意,php版本必須是7.0以及7.0以上的版本。html
下載源碼的時候要注意,swoole2.0及之後版本再也不支持PHP5.xmysql
git clone https://github.com/swoole/swoole-src.gitgit
./configure --with-php-config=/usr/local/php/bin/php-configgithub
注意:若是下載的swoole 2.x,而php版本低於7.0,在這一步會失敗,請下載正確源碼版本web
php -msql
<?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();
向服務器發起請求:shell
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的結構(屬性)。apache
<?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
顯示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。
<?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完成
<?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;
<?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 父進程加鎖 子進程等待父進程解鎖 主進程釋放鎖 子進程加鎖 子進程退出
經過傳入域名,返回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);
<?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 ) )