文字

范例

Example #1 Simple HTTP client

<?php
// Read callback
function  readcb ( $bev $base ) {
    
//$input = $bev->input; //$bev->getInput();

    //$pos = $input->search("TTP");
    
$pos  $bev -> input -> search ( "TTP" );

    while ((
$n  $bev -> input -> remove ( $buf 1024 )) >  0 ) {
        echo 
$buf ;
    }
}

// Event callback
function  eventcb ( $bev $events $base ) {
    if (
$events  EventBufferEvent :: CONNECTED ) {
        echo 
"Connected.\n" ;
    } elseif (
$events  & ( EventBufferEvent :: ERROR  EventBufferEvent :: EOF )) {
        if (
$events  EventBufferEvent :: ERROR ) {
            echo 
"DNS error: " $bev -> getDnsErrorString (),  PHP_EOL ;
        }

        echo 
"Closing\n" ;
        
$base -> exit ();
        exit(
"Done\n" );
    }
}

if (
$argc  !=  3 ) {
    echo <<<EOS
Trivial HTTP 0.x client
Syntax: php 
{ $argv [ 0 ]}  [hostname] [resource]
Example: php 
{ $argv [ 0 ]}  www.google.com /

EOS;
    exit();
}

$base  = new  EventBase ();

$dns_base  = new  EventDnsBase ( $base TRUE );  // We'll use async DNS resolving
if (! $dns_base ) {
    exit(
"Failed to init DNS Base\n" );
}

$bev  = new  EventBufferEvent ( $base   NULL ,
    
EventBufferEvent :: OPT_CLOSE_ON_FREE  EventBufferEvent :: OPT_DEFER_CALLBACKS ,
    
"readcb"   NULL "eventcb"
);
if (!
$bev ) {
    exit(
"Failed creating bufferevent socket\n" );
}

//$bev->setCallbacks("readcb",  NULL, "eventcb", $base);
$bev -> enable ( Event :: READ  Event :: WRITE );

$output  $bev -> output //$bev->getOutput();
if (! $output -> add (
    
"GET  { $argv [ 2 ]}  HTTP/1.0\r\n" .
    
"Host:  { $argv [ 1 ]} \r\n" .
    
"Connection: Close\r\n\r\n"
)) {
    exit(
"Failed adding request to output buffer\n" );
}

if (!
$bev -> connectHost ( $dns_base $argv [ 1 ],  80 EventUtil :: AF_UNSPEC )) {
    exit(
"Can't connect to host  { $argv [ 1 ]} \n" );
}

$base -> dispatch ();
?>

以上例程的输出类似于:

Connected.
HTTP/1.1 301 Moved Permanently
Date: Fri, 01 Mar 2013 18:47:48 GMT
Location: http://www.google.co.uk/
Content-Type: text/html; charset=UTF-8
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 221
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Age: 133438
Expires: Sat, 30 Mar 2013 05:39:28 GMT
Connection: close<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.co.uk/">here</A>.
</BODY></HTML>
Closing
Done

Example #2 HTTP client using asynchronous DNS resolver

<?php


// Read callback
function  readcb ( $bev $base ) {
    
$input  $bev -> getInput ();

    while ((
$n  $input -> remove ( $buf 1024 )) >  0 ) {
        echo 
$buf ;
    }
}

// Event callback
function  eventcb ( $bev $events $base ) {
    if (
$events  EventBufferEvent :: CONNECTED ) {
        echo 
"Connected.\n" ;
    } elseif (
$events  & ( EventBufferEvent :: ERROR  EventBufferEvent :: EOF )) {
        if (
$events  EventBufferEvent :: ERROR ) {
            echo 
"DNS error: " $bev -> getDnsErrorString (),  PHP_EOL ;
        }

        echo 
"Closing\n" ;
        
$base -> exit ();
        exit(
"Done\n" );
    }
}

$base  = new  EventBase ();

echo 
"step 1\n" ;
$bev  = new  EventBufferEvent ( $base   NULL ,
    
EventBufferEvent :: OPT_CLOSE_ON_FREE  EventBufferEvent :: OPT_DEFER_CALLBACKS );
if (!
$bev ) {
    exit(
"Failed creating bufferevent socket\n" );
}

echo 
"step 2\n" ;
$bev -> setCallbacks ( "readcb"   NULL "eventcb" $base );
$bev -> enable ( Event :: READ  Event :: WRITE );

echo 
"step 3\n" ;
// Send request
$output  $bev -> getOutput ();
if (!
$output -> add (
    
"GET /index.cphp HTTP/1.0\r\n" .
    
"Connection: Close\r\n\r\n"
)) {
    exit(
"Failed adding request to output buffer\n" );
}


if (! $bev -> connect ( "127.0.0.1:80" )) {
    exit(
"Can't connect to host\n" );
}

// Dispatch pending events
$base -> dispatch ();
?>

Example #3 Echo server

<?php


class  MyListenerConnection  {
    private 
$bev $base ;

    public function 
__destruct () {
        
$this -> bev -> free ();
    }

    public function 
__construct ( $base $fd ) {
        
$this -> base  $base ;

        
$this -> bev  = new  EventBufferEvent ( $base $fd EventBufferEvent :: OPT_CLOSE_ON_FREE );

        
$this -> bev -> setCallbacks (array( $this "echoReadCallback" ),  NULL ,
            array(
$this "echoEventCallback" ),  NULL );

        if (!
$this -> bev -> enable ( Event :: READ )) {
            echo 
"Failed to enable READ\n" ;
            return;
        }
    }

    public function 
echoReadCallback ( $bev $ctx ) {
        
// Copy all the data from the input buffer to the output buffer

        // Variant #1
        
$bev -> output -> addBuffer ( $bev -> input );

        

        
    
}

    public function 
echoEventCallback ( $bev $events $ctx ) {
        if (
$events  EventBufferEvent :: ERROR ) {
            echo 
"Error from bufferevent\n" ;
        }

        if (
$events  & ( EventBufferEvent :: EOF  EventBufferEvent :: ERROR )) {
            
//$bev->free();
            
$this -> __destruct ();
        }
    }
}

class 
MyListener  {
    public 
$base ,
        
$listener ,
        
$socket ;
    private 
$conn  = array();

    public function 
__destruct () {
        foreach (
$this -> conn  as & $c $c  NULL ;
    }

    public function 
__construct ( $port ) {
        
$this -> base  = new  EventBase ();
        if (!
$this -> base ) {
            echo 
"Couldn't open event base" ;
            exit(
1 );
        }

        
// Variant #1
        

        // Variant #2
         
$this -> listener  = new  EventListener ( $this -> base ,
             array(
$this "acceptConnCallback" ),  $this -> base ,
             
EventListener :: OPT_CLOSE_ON_FREE  EventListener :: OPT_REUSEABLE , - 1 ,
             
"0.0.0.0: $port " );

        if (!
$this -> listener ) {
            echo 
"Couldn't create listener" ;
            exit(
1 );
        }

        
$this -> listener -> setErrorCallback (array( $this "accept_error_cb" ));
    }

    public function 
dispatch () {
        
$this -> base -> dispatch ();
    }

    
// This callback is invoked when there is data to read on $bev
    
public function  acceptConnCallback ( $listener $fd $address $ctx ) {
        
// We got a new connection! Set up a bufferevent for it. */
        
$base  $this -> base ;
        
$this -> conn [] = new  MyListenerConnection ( $base $fd );
    }

    public function 
accept_error_cb ( $listener $ctx ) {
        
$base  $this -> base ;

        
fprintf ( STDERR "Got an error %d (%s) on the listener. "
            
. "Shutting down.\n" ,
            
EventUtil :: getLastSocketErrno (),
            
EventUtil :: getLastSocketError ());

        
$base -> exit ( NULL );
    }
}

$port  9808 ;

if (
$argc  1 ) {
    
$port  = (int)  $argv [ 1 ];
}
if (
$port  <=  ||  $port  65535 ) {
    exit(
"Invalid port" );
}

$l  = new  MyListener ( $port );
$l -> dispatch ();
?>

Example #4 SSL echo server

<?php


class  MySslEchoServer  {
    public 
$port ,
        
$base ,
        
$bev ,
        
$listener ,
        
$ctx ;

    function 
__construct  ( $port $host  "127.0.0.1" ) {
        
$this -> port  $port ;
        
$this -> ctx  $this -> init_ssl ();
        if (!
$this -> ctx ) {
            exit(
"Failed creating SSL context\n" );
        }

        
$this -> base  = new  EventBase ();
        if (!
$this -> base ) {
            exit(
"Couldn't open event base\n" );
        }

        
$this -> listener  = new  EventListener ( $this -> base ,
            array(
$this "ssl_accept_cb" ),  $this -> ctx ,
            
EventListener :: OPT_CLOSE_ON_FREE  EventListener :: OPT_REUSEABLE ,
            -
1 " $host : $port " );
        if (!
$this -> listener ) {
            exit(
"Couldn't create listener\n" );
        }

        
$this -> listener -> setErrorCallback (array( $this "accept_error_cb" ));
    }
    function 
dispatch () {
        
$this -> base -> dispatch ();
    }

    
// This callback is invoked when there is data to read on $bev.
    
function  ssl_read_cb ( $bev $ctx ) {
        
$in  $bev -> input //$bev->getInput();

        
printf ( "Received %zu bytes\n" $in -> length );
        
printf ( "----- data ----\n" );
        
printf ( "%ld:\t%s\n" , (int)  $in -> length $in -> pullup (- 1 ));

        
$bev -> writeBuffer ( $in );
    }

    
// This callback is invoked when some even occurs on the event listener,
    // e.g. connection closed, or an error occured
    
function  ssl_event_cb ( $bev $events $ctx ) {
        if (
$events  EventBufferEvent :: ERROR ) {
            
// Fetch errors from the SSL error stack
            
while ( $err  $bev -> sslError ()) {
                
fprintf ( STDERR "Bufferevent error %s.\n" $err );
            }
        }

        if (
$events  & ( EventBufferEvent :: EOF  EventBufferEvent :: ERROR )) {
            
$bev -> free ();
        }
    }

    
// This callback is invoked when a client accepts new connection
    
function  ssl_accept_cb ( $listener $fd $address $ctx ) {
        
// We got a new connection! Set up a bufferevent for it.
        
$this -> bev  EventBufferEvent :: sslSocket ( $this -> base $fd $this -> ctx ,
            
EventBufferEvent :: SSL_ACCEPTING EventBufferEvent :: OPT_CLOSE_ON_FREE );

        if (!
$this -> bev ) {
            echo 
"Failed creating ssl buffer\n" ;
            
$this -> base -> exit ( NULL );
            exit(
1 );
        }

        
$this -> bev -> enable ( Event :: READ );
        
$this -> bev -> setCallbacks (array( $this "ssl_read_cb" ),  NULL ,
            array(
$this "ssl_event_cb" ),  NULL );
    }

    
// This callback is invoked when we failed to setup new connection for a client
    
function  accept_error_cb ( $listener $ctx ) {
        
fprintf ( STDERR "Got an error %d (%s) on the listener. "
            
. "Shutting down.\n" ,
            
EventUtil :: getLastSocketErrno (),
            
EventUtil :: getLastSocketError ());

        
$this -> base -> exit ( NULL );
    }

    
// Initialize SSL structures, create an EventSslContext
    // Optionally create self-signed certificates
    
function  init_ssl () {
        
// We *must* have entropy. Otherwise there's no point to crypto.
        
if (! EventUtil :: sslRandPoll ()) {
            exit(
"EventUtil::sslRandPoll failed\n" );
        }

        
$local_cert  __DIR__ . "/cert.pem" ;
        
$local_pk    __DIR__ . "/privkey.pem" ;

        if (!
file_exists ( $local_cert ) || ! file_exists ( $local_pk )) {
            echo 
"Couldn't read  $local_cert  or  $local_pk  file.  To generate a key\n" ,
                
"and self-signed certificate, run:\n" ,
                
"  openssl genrsa -out  $local_pk  2048\n" ,
                
"  openssl req -new -key  $local_pk  -out cert.req\n" ,
                
"  openssl x509 -req -days 365 -in cert.req -signkey  $local_pk  -out  $local_cert \n" ;

            return 
FALSE ;
        }

        
$ctx  = new  EventSslContext ( EventSslContext :: SSLv3_SERVER_METHOD , array (
             
EventSslContext :: OPT_LOCAL_CERT   =>  $local_cert ,
             
EventSslContext :: OPT_LOCAL_PK     =>  $local_pk ,
             
//EventSslContext::OPT_PASSPHRASE  => "echo server",
             
EventSslContext :: OPT_VERIFY_PEER  =>  true ,
             
EventSslContext :: OPT_ALLOW_SELF_SIGNED  =>  false ,
        ));

        return 
$ctx ;
    }
}

// Allow to override the port
$port  9999 ;
if (
$argc  1 ) {
    
$port  = (int)  $argv [ 1 ];
}
if (
$port  <=  ||  $port  65535 ) {
    exit(
"Invalid port\n" );
}


$l  = new  MySslEchoServer ( $port );
$l -> dispatch ();
?>

Example #5 Signal handler

<?php

class  MyEventSignal  {
    private 
$base ;

    function 
__construct ( $base ) {
        
$this -> base  $base ;
    }

    function 
eventSighandler ( $no $c ) {
        echo 
"Caught signal  $no \n" ;
        
event_base_loopexit ( $c -> base );
    }
}

$base  event_base_new ();
$c     = new  MyEventSignal ( $base );
$no    SIGTERM ;
$ev    evsignal_new ( $base $no , array( $c , 'eventSighandler' ),  $c );

evsignal_add ( $ev );

event_base_loop ( $base );
?>

Example #6 Use libevent's loop to process requests of `eio' extension

<?php
// Callback for eio_nop()
function  my_nop_cb ( $d $r ) {
    echo 
"step 6\n" ;
}

$dir  "/tmp/abc-eio-temp" ;
if (
file_exists ( $dir )) {
    
rmdir ( $dir );
}

echo 
"step 1\n" ;

$base  = new  EventBase ();

echo 
"step 2\n" ;

eio_init ();

eio_mkdir ( $dir 0750 EIO_PRI_DEFAULT "my_nop_cb" );

$event  = new  Event ( $base eio_get_event_stream (),
    
Event :: READ  Event :: PERSIST , function ( $fd $events $base ) {
    echo 
"step 5\n" ;

    while (
eio_nreqs ()) {
        
eio_poll ();
    }

    
$base -> stop ();
}, 
$base );

echo 
"step 3\n" ;

$event -> add ();

echo 
"step 4\n" ;

$base -> dispatch ();

echo 
"Done\n" ;
?>

Example #7 Miscellaneous

<?php

echo  "Supported methods:\n" ;
foreach (
Event :: getSupportedMethods () as  $m ) {
    echo 
$m PHP_EOL ;
}

// Avoiding "select" method
$cfg  = new  EventConfig ();
if (
$cfg -> avoidMethod ( "select" )) {
    echo 
"`select' method avoided\n" ;
}

// Create event_base associated with the config
$base  = new  EventBase ( $cfg );
echo 
"Event method used: " $base -> getMethod (),  PHP_EOL ;

echo 
"Features:\n" ;
$features  $base -> getFeatures ();
(
$features  EventConfig :: FEATURE_ET ) and print( "ET - edge-triggered IO\n" );
(
$features  EventConfig :: FEATURE_O1 ) and print( "O1 - O(1) operation for adding/deletting events\n" );
(
$features  EventConfig :: FEATURE_FDS ) and print( "FDS - arbitrary file descriptor types, and not just sockets\n" );

// Require FDS feature
if ( $cfg -> requireFeatures ( EventConfig :: FEATURE_FDS )) {
    echo 
"FDS feature is now requried\n" ;

    
$base  = new  EventBase ( $cfg );
    (
$base -> getFeatures () &  EventConfig :: FEATURE_FDS )
        and print(
"FDS - arbitrary file descriptor types, and not just sockets\n" );
}



$base  = new  EventBase ();
$event  = new  Event ( $base STDIN Event :: READ  Event :: PERSIST , function ( $fd $events $arg ) {
    static 
$max_iterations  0 ;

    if (++
$max_iterations  >=  5 ) {
        

        
echo  "Stopping...\n" ;
        
$arg [ 0 ]-> exit ( 2.33 );
    }

    echo 
fgets ( $fd );
}, array (&
$base ));

$event -> add ();
$base -> loop ();

?>

Example #8 Simple HTTP server

<?php


function  _http_dump ( $req $data ) {
    static 
$counter       0 ;
    static 
$max_requests  2 ;

    if (++
$counter  >=  $max_requests )  {
        echo 
"Counter reached max requests  $max_requests . Exiting\n" ;
        exit();
    }

    echo 
__METHOD__ " called\n" ;
    echo 
"request:" var_dump ( $req );
    echo 
"data:" var_dump ( $data );

    echo 
"\n===== DUMP =====\n" ;
    echo 
"Command:" $req -> getCommand (),  PHP_EOL ;
    echo 
"URI:" $req -> getUri (),  PHP_EOL ;
    echo 
"Input headers:" var_dump ( $req -> getInputHeaders ());
    echo 
"Output headers:" var_dump ( $req -> getOutputHeaders ());

    echo 
"\n >> Sending reply ..." ;
    
$req -> sendReply ( 200 "OK" );
    echo 
"OK\n" ;

    echo 
"\n >> Reading input buffer ...\n" ;
    
$buf  $req -> getInputBuffer ();
    while (
$s  $buf -> readLine ( EventBuffer :: EOL_ANY )) {
        echo 
$s PHP_EOL ;
    }
    echo 
"No more data in the buffer\n" ;
}

function 
_http_about ( $req ) {
    echo 
__METHOD__ PHP_EOL ;
    echo 
"URI: " $req -> getUri (),  PHP_EOL ;
    echo 
"\n >> Sending reply ..." ;
    
$req -> sendReply ( 200 "OK" );
    echo 
"OK\n" ;
}

function 
_http_default ( $req $data ) {
    echo 
__METHOD__ PHP_EOL ;
    echo 
"URI: " $req -> getUri (),  PHP_EOL ;
    echo 
"\n >> Sending reply ..." ;
    
$req -> sendReply ( 200 "OK" );
    echo 
"OK\n" ;
}

$port  8010 ;
if (
$argc  1 ) {
    
$port  = (int)  $argv [ 1 ];
}
if (
$port  <=  ||  $port  65535 ) {
    exit(
"Invalid port" );
}

$base  = new  EventBase ();
$http  = new  EventHttp ( $base );
$http -> setAllowedMethods ( EventHttpRequest :: CMD_GET  EventHttpRequest :: CMD_POST );

$http -> setCallback ( "/dump" "_http_dump" , array( 4 8 ));
$http -> setCallback ( "/about" "_http_about" );
$http -> setDefaultCallback ( "_http_default" "custom data value" );

$http -> bind ( "0.0.0.0" 8010 );
$base -> loop ();
?>

以上例程的输出类似于:

a=12
HTTP/1.0 200 OK
Content-Type: text/html; charset=ISO-8859-1
Connection: closeHTTP/1.0 200 OK
Content-Type: text/html; charset=ISO-8859-1
Connection: close
(press Enter)HTTP/1.0 200 OK
Content-Type: text/html; charset=ISO-8859-1
Connection: close

Example #9 Simple HTTPS server

<?php


function  _http_dump ( $req $data ) {
    static 
$counter       0 ;
    static 
$max_requests  200 ;

    if (++
$counter  >=  $max_requests )  {
        echo 
"Counter reached max requests  $max_requests . Exiting\n" ;
        exit();
    }

    echo 
__METHOD__ " called\n" ;
    echo 
"request:" var_dump ( $req );
    echo 
"data:" var_dump ( $data );

    echo 
"\n===== DUMP =====\n" ;
    echo 
"Command:" $req -> getCommand (),  PHP_EOL ;
    echo 
"URI:" $req -> getUri (),  PHP_EOL ;
    echo 
"Input headers:" var_dump ( $req -> getInputHeaders ());
    echo 
"Output headers:" var_dump ( $req -> getOutputHeaders ());

    echo 
"\n >> Sending reply ..." ;
    
$req -> sendReply ( 200 "OK" );
    echo 
"OK\n" ;

    
$buf  $req -> getInputBuffer ();
    echo 
"\n >> Reading input buffer (" $buf -> length ") ...\n" ;
    while (
$s  $buf -> read ( 1024 )) {
        echo 
$s ;
    }
    echo 
"\nNo more data in the buffer\n" ;
}

function 
_http_about ( $req ) {
    echo 
__METHOD__ PHP_EOL ;
    echo 
"URI: " $req -> getUri (),  PHP_EOL ;
    echo 
"\n >> Sending reply ..." ;
    
$req -> sendReply ( 200 "OK" );
    echo 
"OK\n" ;
}

function 
_http_default ( $req $data ) {
    echo 
__METHOD__ PHP_EOL ;
    echo 
"URI: " $req -> getUri (),  PHP_EOL ;
    echo 
"\n >> Sending reply ..." ;
    
$req -> sendReply ( 200 "OK" );
    echo 
"OK\n" ;
}

function 
_http_400 ( $req ) {
    
$req -> sendError ( 400 );
}

function 
_init_ssl () {
    
$local_cert  __DIR__ . "/ssl-echo-server/cert.pem" ;
    
$local_pk    __DIR__ . "/ssl-echo-server/privkey.pem" ;

    
$ctx  = new  EventSslContext ( EventSslContext :: SSLv3_SERVER_METHOD , array (
        
EventSslContext :: OPT_LOCAL_CERT   =>  $local_cert ,
        
EventSslContext :: OPT_LOCAL_PK     =>  $local_pk ,
        
//EventSslContext::OPT_PASSPHRASE  => "test",
        
EventSslContext :: OPT_ALLOW_SELF_SIGNED  =>  true ,
    ));

    return 
$ctx ;
}

$port  9999 ;
if (
$argc  1 ) {
    
$port  = (int)  $argv [ 1 ];
}
if (
$port  <=  ||  $port  65535 ) {
    exit(
"Invalid port" );
}
$ip  '0.0.0.0' ;

$base  = new  EventBase ();
$ctx   _init_ssl ();
$http  = new  EventHttp ( $base $ctx );
$http -> setAllowedMethods ( EventHttpRequest :: CMD_GET  EventHttpRequest :: CMD_POST );

$http -> setCallback ( "/dump" "_http_dump" , array( 4 8 ));
$http -> setCallback ( "/about" "_http_about" );
$http -> setCallback ( "/err400" "_http_400" );
$http -> setDefaultCallback ( "_http_default" "custom data value" );

$http -> bind ( $ip $port );
$base -> dispatch ();

Example #10 OpenSSL connection

<?php


function  _request_handler ( $req $base ) {
    echo 
__FUNCTION__ PHP_EOL ;

    if (
is_null ( $req )) {
        echo 
"Timed out\n" ;
    } else {
        
$response_code  $req -> getResponseCode ();

        if (
$response_code  ==  0 ) {
            echo 
"Connection refused\n" ;
        } elseif (
$response_code  !=  200 ) {
            echo 
"Unexpected response:  $response_code \n" ;
        } else {
            echo 
"Success:  $response_code \n" ;
            
$buf  $req -> getInputBuffer ();
            echo 
"Body:\n" ;
            while (
$s  $buf -> readLine ( EventBuffer :: EOL_ANY )) {
                echo 
$s PHP_EOL ;
            }
        }
    }

    
$base -> exit ( NULL );
}

function 
_init_ssl () {
    
$ctx  = new  EventSslContext ( EventSslContext :: SSLv3_CLIENT_METHOD , array ());

    return 
$ctx ;
}


// Allow to override the port
$port  9999 ;
if (
$argc  1 ) {
    
$port  = (int)  $argv [ 1 ];
}
if (
$port  <=  ||  $port  65535 ) {
    exit(
"Invalid port\n" );
}
$host  '127.0.0.1' ;

$ctx  _init_ssl ();
if (!
$ctx ) {
    
trigger_error ( "Failed creating SSL context" E_USER_ERROR );
}

$base  = new  EventBase ();
if (!
$base ) {
    
trigger_error ( "Failed to initialize event base" E_USER_ERROR );
}

$conn  = new  EventHttpConnection ( $base NULL $host $port $ctx );
$conn -> setTimeout ( 50 );

$req  = new  EventHttpRequest ( "_request_handler" $base );
$req -> addHeader ( "Host" $host EventHttpRequest :: OUTPUT_HEADER );
$buf  $req -> getOutputBuffer ();
$buf -> add ( "<html>HTML TEST</html>" );
//$req->addHeader("Content-Length", $buf->length, EventHttpRequest::OUTPUT_HEADER);
//$req->addHeader("Connection", "close", EventHttpRequest::OUTPUT_HEADER);
$conn -> makeRequest ( $req EventHttpRequest :: CMD_POST "/dump" );

$base -> dispatch ();
echo 
"END\n" ;
?>

Example #11 EventHttpConnection::makeRequest() example

<?php
function  _request_handler ( $req $base ) {
    echo 
__FUNCTION__ PHP_EOL ;

    if (
is_null ( $req )) {
        echo 
"Timed out\n" ;
    } else {
        
$response_code  $req -> getResponseCode ();

        if (
$response_code  ==  0 ) {
            echo 
"Connection refused\n" ;
        } elseif (
$response_code  !=  200 ) {
            echo 
"Unexpected response:  $response_code \n" ;
        } else {
            echo 
"Success:  $response_code \n" ;
            
$buf  $req -> getInputBuffer ();
            echo 
"Body:\n" ;
            while (
$s  $buf -> readLine ( EventBuffer :: EOL_ANY )) {
                echo 
$s PHP_EOL ;
            }
        }
    }

    
$base -> exit ( NULL );
}

$address  "127.0.0.1" ;
$port  80 ;

$base  = new  EventBase ();
$conn  = new  EventHttpConnection ( $base NULL $address $port );
$conn -> setTimeout ( 5 );
$req  = new  EventHttpRequest ( "_request_handler" $base );

$req -> addHeader ( "Host" $address EventHttpRequest :: OUTPUT_HEADER );
$req -> addHeader ( "Content-Length" "0" EventHttpRequest :: OUTPUT_HEADER );
$conn -> makeRequest ( $req EventHttpRequest :: CMD_GET "/index.cphp" );

$base -> loop ();
?>

以上例程的输出类似于:

_request_handler
Success: 200
Body:
PHP, date:
2013-03-13T20:27:52+05:00

Example #12 Connection listener based on a UNIX domain socket

<?php


class  MyListenerConnection  {
    private 
$bev $base ;

    public function 
__destruct () {
        if (
$this -> bev ) {
            
$this -> bev -> free ();
        }
    }

    public function 
__construct ( $base $fd ) {
        
$this -> base  $base ;

        
$this -> bev  = new  EventBufferEvent ( $base $fd EventBufferEvent :: OPT_CLOSE_ON_FREE );

        
$this -> bev -> setCallbacks (array( $this "echoReadCallback" ),  NULL ,
            array(
$this "echoEventCallback" ),  NULL );

        if (!
$this -> bev -> enable ( Event :: READ )) {
            echo 
"Failed to enable READ\n" ;
            return;
        }
    }

    public function 
echoReadCallback ( $bev $ctx ) {
        
// Copy all the data from the input buffer to the output buffer
        
$bev -> output -> addBuffer ( $bev -> input );
    }

    public function 
echoEventCallback ( $bev $events $ctx ) {
        if (
$events  EventBufferEvent :: ERROR ) {
            echo 
"Error from bufferevent\n" ;
        }

        if (
$events  & ( EventBufferEvent :: EOF  EventBufferEvent :: ERROR )) {
            
$bev -> free ();
            
$bev  NULL ;
        }
    }
}

class 
MyListener  {
    public 
$base ,
        
$listener ,
        
$socket ;
    private 
$conn  = array();

    public function 
__destruct () {
        foreach (
$this -> conn  as & $c $c  NULL ;
    }

    public function 
__construct ( $sock_path ) {
        
$this -> base  = new  EventBase ();
        if (!
$this -> base ) {
            echo 
"Couldn't open event base" ;
            exit(
1 );
        }

        if (
file_exists ( $sock_path )) {
            
unlink ( $sock_path );
        }

         
$this -> listener  = new  EventListener ( $this -> base ,
             array(
$this "acceptConnCallback" ),  $this -> base ,
             
EventListener :: OPT_CLOSE_ON_FREE  EventListener :: OPT_REUSEABLE , - 1 ,
             
"unix: $sock_path " );

        if (!
$this -> listener ) {
            
trigger_error ( "Couldn't create listener" E_USER_ERROR );
        }

        
$this -> listener -> setErrorCallback (array( $this "accept_error_cb" ));
    }

    public function 
dispatch () {
        
$this -> base -> dispatch ();
    }

    
// This callback is invoked when there is data to read on $bev
    
public function  acceptConnCallback ( $listener $fd $address $ctx ) {
        
// We got a new connection! Set up a bufferevent for it. */
        
$base  $this -> base ;
        
$this -> conn [] = new  MyListenerConnection ( $base $fd );
    }

    public function 
accept_error_cb ( $listener $ctx ) {
        
$base  $this -> base ;

        
fprintf ( STDERR "Got an error %d (%s) on the listener. "
            
. "Shutting down.\n" ,
            
EventUtil :: getLastSocketErrno (),
            
EventUtil :: getLastSocketError ());

        
$base -> exit ( NULL );
    }
}

if (
$argc  <=  1 ) {
    exit(
"Socket path is not provided\n" );
}
$sock_path  $argv [ 1 ];

$l  = new  MyListener ( $sock_path );
$l -> dispatch ();
?>

Example #13 Simple SMTP server

<?php
 


class  Handler  {
    public 
$domainName  FALSE ;
    public 
$connections  = [];
    public 
$buffers  = [];
    public 
$maxRead  256000 ;

    public function 
__construct () {
        
$this -> ctx  = new  EventSslContext ( EventSslContext :: SSLv3_SERVER_METHOD , [
            
EventSslContext :: OPT_LOCAL_CERT   =>  'cert.pem' ,
            
EventSslContext :: OPT_LOCAL_PK     =>  'privkey.pem' ,
            
//EventSslContext::OPT_PASSPHRASE  => '',
            
EventSslContext :: OPT_VERIFY_PEER  =>  false // change to true with authentic cert
            
EventSslContext :: OPT_ALLOW_SELF_SIGNED  =>  true  // change to false with authentic cert
        
]);

        
$this -> base  = new  EventBase ();
        if (!
$this -> base ) {
            exit(
"Couldn't open event base\n" );
        }

        if (!
$this -> listener  = new  EventListener ( $this -> base ,
            [
$this 'ev_accept' ],
            
$this -> ctx ,
            
EventListener :: OPT_CLOSE_ON_FREE  EventListener :: OPT_REUSEABLE ,
            -
1 ,
            
'0.0.0.0:25' ))
        {
            exit(
"Couldn't create listener\n" );
        }

        
$this -> listener -> setErrorCallback ([ $this 'ev_error' ]);
        
$this -> base -> dispatch ();
    }

    public function 
ev_accept ( $listener $fd $address $ctx ) {
        static 
$id  0 ;
        
$id  +=  1 ;

        
$this -> connections [ $id ][ 'clientData' ] =  '' ;
        
$this -> connections [ $id ][ 'cnx' ] = new  EventBufferEvent ( $this -> base $fd ,
            
EventBufferEvent :: OPT_CLOSE_ON_FREE );

        if (!
$this -> connections [ $id ][ 'cnx' ]) {
            echo 
"Failed creating buffer\n" ;
            
$this -> base -> exit ( NULL );
            exit(
1 );
        }

        
$this -> connections [ $id ][ 'cnx' ]-> setCallbacks ([ $this "ev_read" ],  NULL ,
            [
$this 'ev_error' ],  $id );
        
$this -> connections [ $id ][ 'cnx' ]-> enable ( Event :: READ  Event :: WRITE );

        
$this -> ev_write ( $id '220 ' . $this -> domainName . " wazzzap?\r\n" );
    }

    function 
ev_error ( $listener $ctx ) {
        
$errno  EventUtil :: getLastSocketErrno ();

        
fprintf ( STDERR "Got an error %d (%s) on the listener. Shutting down.\n" ,
            
$errno EventUtil :: getLastSocketError ());

        if (
$errno  !=  0 ) {
            
$this -> base -> exit ( NULL );
            exit();
        }
    }

    public function 
ev_close ( $id ) {
        
$this -> connections [ $id ][ 'cnx' ]-> disable ( Event :: READ  Event :: WRITE );
        unset(
$this -> connections [ $id ]);
    }

    protected function 
ev_write ( $id $string ) {
        echo 
'S(' . $id . '): ' . $string ;
        
$this -> connections [ $id ][ 'cnx' ]-> write ( $string );
    }

    public function 
ev_read ( $buffer $id ) {
        while(
$buffer -> input -> length  0 ) {
            
$this -> connections [ $id ][ 'clientData' ] .=  $buffer -> input -> read ( $this -> maxRead );
            
$clientDataLen  strlen ( $this -> connections [ $id ][ 'clientData' ]);

            if(
$this -> connections [ $id ][ 'clientData' ][ $clientDataLen - 1 ] ==  "\n"
                
&&  $this -> connections [ $id ][ 'clientData' ][ $clientDataLen - 2 ] ==  "\r" )
            {
                
// remove the trailing \r\n
                
$line  substr ( $this -> connections [ $id ][ 'clientData' ],  0 ,
                    
strlen ( $this -> connections [ $id ][ 'clientData' ]) -  2 );

                
$this -> connections [ $id ][ 'clientData' ] =  '' ;
                
$this -> cmd ( $buffer $id $line );
            }
        }
    }

    protected function 
cmd ( $buffer $id $line ) {
        switch (
$line ) {
            case 
strncmp ( 'EHLO ' $line 4 ):
                
$this -> ev_write ( $id "250-STARTTLS\r\n" );
                
$this -> ev_write ( $id "250 OK ehlo\r\n" );
                break;

            case 
strncmp ( 'HELO ' $line 4 ):
                
$this -> ev_write ( $id "250-STARTTLS\r\n" );
                
$this -> ev_write ( $id "250 OK helo\r\n" );
                break;

            case 
strncmp ( 'QUIT' $line 3 ):
                
$this -> ev_write ( $id "250 OK quit\r\n" );
                
$this -> ev_close ( $id );
                break;

            case 
strncmp ( 'STARTTLS' $line 3 ):
                
$this -> ev_write ( $id "220 Ready to start TLS\r\n" );
                
$this -> connections [ $id ][ 'cnx' ] =  EventBufferEvent :: sslFilter ( $this -> base ,
                    
$this -> connections [ $id ][ 'cnx' ],  $this -> ctx ,
                    
EventBufferEvent :: SSL_ACCEPTING ,
                    
EventBufferEvent :: OPT_CLOSE_ON_FREE );
                
$this -> connections [ $id ][ 'cnx' ]-> setCallbacks ([ $this "ev_read" ],  NULL , [ $this 'ev_error' ],  $id );
                
$this -> connections [ $id ][ 'cnx' ]-> enable ( Event :: READ  Event :: WRITE );
                break;

            default:
                echo 
'unknown command: ' . $line . "\n" ;
                break;
        }
    }
}

new 
Handler ();

用户评论:

[#1] Bas Vijfwinkel [2015-06-26 09:17:32]

In order to use certain features used in the examples above here you need a very recent version of libevent (>= 2.1).
Although 'pecl install event' will not show any errors, certain features are disabled and certain function calls might use a different number of parameters.
For example EventHttp will throw a warning that the number of parameters should be 1 instead of 2 (when using it with a SSL context) and as a bonus cause a segmentation fault.

On some distributions of Linux, the stable libevent library might not be recent enough for all features to be enabled and you might need to use an alpha version.

You can install an alpha version of libevent next to the stable version that might already be on your machine.
The basic steps are:
- download the alpha tarball to a folder e.g libevent-2.1.3-alpha.tar.gz
- tar zxvf libevent-2.1.3-alpha.tar.gz
- cd libevent-2.1.3-alpha
- ./configure --prefix=/opt/libevent-alpha
- make
- make install

Now the alpha version of libevent is created in /opt/libevent-alpha.

Before running pecl, first export the library folder of libevent so that pecl knows where your most recent libevent stuff is:
export LD_LIBRARY_PATH=/opt/libevent-2.1.3-alpha/lib
Without this export I couldn't get pecl to use the correct libevent

Now run 'pecl install event'
and when asked libevent installation prefix [/usr] : 
enter :  /opt/libevent-2.1.3-alpha
Now pecl will use your alpha version of libevent instead of the default version.

If everything goes well then you should be able to enjoy the full glory of this wonderfull extension.

If you try to install a very recent version of libevent on a system with a  old version of openssl (0.9), you also need to update that because there are some dependencies in libevent that do not work with 0.9

上一篇: 下一篇: