zoukankan      html  css  js  c++  java
  • 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边缘触发

    下面看一下一个简单的用例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?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 ");
    }
     
    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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <?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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    <?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
    }
  • 相关阅读:
    Step one : 熟悉Unix/Linux Shell 常见命令行 (三)
    Step one : 熟悉Unix/Linux Shell 常见命令行 (一)
    PLAN: step one
    PLAN : 入门题目 ( update )
    SZU : A11 Sequence
    SZU:B85 Alec's Eggs
    codeforces 518B. Tanya and Postcard 解题报告
    BestCoder8 1001.Summary(hdu 4989) 解题报告
    hdu 1556.Color the ball 解题报告
    codeforces 515C. Drazil and Factorial 解题报告
  • 原文地址:https://www.cnblogs.com/setevn/p/7798566.html
Copyright © 2011-2022 走看看