安裝使用swoole

swoole首頁:https://www.swoole.com/

方法1:使用pecl安裝

  pecl install swoolephp

  注意,php版本必須是7.0以及7.0以上的版本。html

 

方法2:編譯源碼安裝

第一步:下載swoole的源碼

  下載源碼的時候要注意,swoole2.0及之後版本再也不支持PHP5.xmysql

git clone  https://github.com/swoole/swoole-src.gitgit

 

第二步:進入源碼目錄,執行phpize命令

 

第三步:配置php-config的路徑

./configure --with-php-config=/usr/local/php/bin/php-configgithub

 

第四步:將php.ini中被禁止的proc_open、proc_get_status、system、exec、shell_exec這幾個函數從其中刪除,由於在make時要用到這幾個函數。

 

第五步:make

  注意:若是下載的swoole 2.x,而php版本低於7.0,在這一步會失敗,請下載正確源碼版本web

 

第六步:make test

 

第七步檢測是否安裝成功

php  -msql

 

使用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();

  向服務器發起請求: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

 

使用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
        )

)
相關文章
相關標籤/搜索