php libevent擴展的簡單用例


  php libevent擴展具有很強大的功能。以下摘自百度百科:

  Libevent 是一個用C語言編寫的、輕量級的開源高性能網絡庫,主要有以下幾個亮點:事件驅動( event-driven),高性能;輕量級,專注於網絡,不如 ACE 那么臃腫龐大;

源代碼相當精煉、易讀;跨平台,支持 Windows、 Linux、 *BSD 和 Mac Os;支持多種 I/O 多路復用技術, epoll、 poll、 dev/poll、 select 和 kqueue 等;支持 I/O,

定時器和信號等事件;注冊事件優先級。

 

  在php 的libevent擴展具有如下函數:

  event_base_free()     釋放資源,這不能銷毀綁定事件
  event_base_loop()     處理事件,根據指定的base來處理事件循環
  event_base_loopbreak()     立即取消事件循環,行為和break語句相同
  event_base_loopexit()     在指定的時間后退出循環
  event_base_new()     創建並且初始事件
  event_base_priority_init()     設定事件的優先級
  event_base_set()     關聯事件到事件base
  event_buffer_base_set()     關聯緩存的事件到event_base
  event_buffer_disable()     禁用一個緩存的事件
  event_buffer_enable()     啟用一個指定的緩存的事件
  event_buffer_fd_set()     改變一個緩存的文件系統描述
  event_buffer_free()     釋放緩存事件
  event_buffer_new()     建立一個新的緩存事件
  event_buffer_priority_set()     緩存事件的優先級設定
  event_buffer_read()     讀取緩存事件中的數據
  event_buffer_set_callback()     給緩存的事件設置或重置回調hansh函數
  event_buffer_timeout_set()     給一個緩存的事件設定超時的讀寫時間
  event_buffer_watermark_set     設置讀寫事件的水印標記
  event_buffer_write()     向緩存事件中寫入數據
  event_add()     向指定的設置中添加一個執行事件
  event_del()     從設置的事件中移除事件
  event_free()     清空事件句柄
  event_new()     創建一個新的事件
  event_set()     准備想要在event_add中添加事件

 

    event_set一些參數的解釋:

  (a) EV_TIMEOUT: 超時
    (b) EV_READ: 只要網絡緩沖中還有數據,回調函數就會被觸發
    (c) EV_WRITE: 只要塞給網絡緩沖的數據被寫完,回調函數就會被觸發
    (d) EV_SIGNAL: POSIX信號量
    (e) EV_PERSIST: 不指定這個屬性的話,回調函數被觸發后事件會被刪除
    (f) EV_ET: Edge-Trigger邊緣觸發

 

下面看一下一個簡單的用例:

<?php
$socket = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);

$base = event_base_new();
$event = event_new();

function read_cb($socket, $flag, $base) {
  fread($socket);
   fwrite("hello world\n");
}

function accept_cb($socket, $flag, $base) {
    $conn = stream_socket_accept($socket, 0);
    stream_set_blocking($conn, 0);
    $event = event_new();
    event_set($event, $conn, EV_READ | EV_PERSIST, 'read_cb', $base);
    event_base_set($event, $base);
    event_add($event);
}

event_set($event, $socket, EV_READ | EV_PERSIST, 'accept_cb', $base);
event_base_set($event, $base);
event_add($event);
event_base_loop($base);

  這一段是摘抄自 韓天峰 的一個PPT上的簡單用例,我來給大家解釋一下:

  首先創建一個 tcp服務,綁定 8000端口。創建一個 event_base,然后創建一個 event,通過 event_set設置 讓event監聽新創建的socket,並給這個event事件設置屬性,可以看到其中指定了回調函數 accept_cb

然后將這個event與base進行綁定,並加入到監聽事件中取,啟動事件循環。

  可以發現 accept_cb做了接受客戶端鏈接,並且又創建了一個event事件,做了跟之前一樣的事情,並且指定了該事件的回調函數是read_cb。 而read_cb函數 做了讀取和寫入操作。

  下面我自己通過整理寫一個客戶端 client.php

<?php
/**
 * author: NickBai
 * createTime: 2016/12/17 0017 下午 3:00
 */
$socket_client = stream_socket_client('tcp://127.0.0.1:2000', $errno, $errstr, 30);
fwrite($socket_client, "hello world!");
sleep(1);
$return = fread($socket_client, 1024);
echo "come from server : " . $return . PHP_EOL;
sleep(2);

fwrite($socket_client, "send again!");
$return = fread($socket_client, 1024);
echo "come from server : " . $return . PHP_EOL;

  我重新整理了一個具有實際可操作的 server 服務端代碼如下

  server.php

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2016/12/17
 * Time: 20:59
 */
$socket = stream_socket_server("tcp://0.0.0.0:2000", $errno, $errstr);

$base = event_base_new();
$event = event_new();

event_set($event, $socket, EV_READ | EV_PERSIST, 'accept_cb', $base);
event_base_set($event, $base);
event_add($event);
event_base_loop($base);

function read_cb($buffer)
{
    static $ct = 0;  
    $ct_last = $ct;  
    $ct_data = '';  
    while ($read = event_buffer_read($buffer, 1024)) {  
        $ct += strlen($read);  
        $ct_data .= $read;  
    }

    $ct_size = ($ct - $ct_last) * 8;  
    echo "client say : " . $ct_data .PHP_EOL;  
    event_buffer_write($buffer, "Received $ct_size byte data");
}

function write_cb($buffer)
{
	echo "我在打醬油 " . PHP_EOL;
}

function error_cb($buffer, $error)
{
	// 客戶端斷開連接之后,清除
	event_buffer_disable($GLOBALS['buffer'], EV_READ | EV_WRITE);  
    event_buffer_free($GLOBALS['buffer']);  
    fclose($GLOBALS['connection']);  
    unset($GLOBALS['buffer'], $GLOBALS['connection']);  
}

function accept_cb($socket, $flag, $base)
{
    $connection = stream_socket_accept($socket);
    stream_set_blocking($connection, 0);

    $buffer = event_buffer_new($connection, 'read_cb', 'write_cb', 'error_cb');  
    event_buffer_base_set($buffer, $base);  
    event_buffer_timeout_set($buffer, 30, 30);  
    event_buffer_watermark_set($buffer, EV_READ, 0, 0xffffff);  
    event_buffer_priority_set($buffer, 10);  
    event_buffer_enable($buffer, EV_READ | EV_PERSIST);  

    // 必須將 $connection 和 $buffer 賦值給一個全局變量,否則無法生效 
    $GLOBALS['connection'] = $connection;
    $GLOBALS['buffer'] = $buffer;  
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM