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 /* * 1. Connect to 127.0.0.1 at port 80 * by means of EventBufferEvent::connect(). * * 2. Request /index.cphp via HTTP/1.0 * using the output buffer. * * 3. Asyncronously read the response and print it to stdout. */
// Read callback function readcb($bev, $base) { $input = $bev->getInput();
/* Connect to the host syncronously. We know the IP, and don't need to resolve DNS. */ 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 /* * Simple echo server based on libevent's connection listener. * * Usage: * 1) In one terminal window run: * * $ php listener.php 9881 * * 2) In another terminal window open up connection, e.g.: * * $ nc 127.0.0.1 9881 * * 3) start typing. The server should repeat the input. */
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);
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());
// 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);
// 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"); }
// 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 */ $base = new EventBase(); $event = new Event($base, STDIN, Event::READ | Event::PERSIST, function ($fd, $events, $arg) { static $max_iterations = 0;
if (++$max_iterations >= 5) { /* exit after 5 iterations with timeout of 2.33 seconds */ echo "Stopping...\n"; $arg[0]->exit(2.33); }
echo fgets($fd); }, array (&$base));
$event->add(); $base->loop(); /* Base }}} */ ?>
Example #8 Simple HTTP server
<?php /* * Simple HTTP server. * * To test it: * 1) Run it on a port of your choice, e.g.: * $ php examples/http.php 8010 * 2) In another terminal connect to some address on this port * and make GET or POST request(others are turned off here), e.g.: * $ nc -t 127.0.0.1 8010 * POST /about HTTP/1.0 * Content-Type: text/plain * Content-Length: 4 * Connection: close * (press Enter) * * It will output * a=12 * HTTP/1.0 200 OK * Content-Type: text/html; charset=ISO-8859-1 * Connection: close * * $ nc -t 127.0.0.1 8010 * GET /dump HTTP/1.0 * Content-Type: text/plain * Content-Encoding: UTF-8 * Connection: close * (press Enter) * * It will output: * HTTP/1.0 200 OK * Content-Type: text/html; charset=ISO-8859-1 * Connection: close * (press Enter) * * $ nc -t 127.0.0.1 8010 * GET /unknown HTTP/1.0 * Connection: close * * It will output: * HTTP/1.0 200 OK * Content-Type: text/html; charset=ISO-8859-1 * Connection: close * * 3) See what the server outputs on the previous terminal window. */
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"; }
$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: close
HTTP/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 /* * Simple HTTPS server. * * 1) Run the server: `php examples/https.php 9999` * 2) Test it: `php examples/ssl-connection.php 9999` */
Example #12
Connection listener based on a UNIX domain socket
<?php /* * Simple echo server based on libevent's connection listener. * * Usage: * 1) In one terminal window run: * * $ php unix-domain-listener.php [path-to-socket] * * 2) In another terminal window open up connection * to the socket, e.g.: * * $ socat - GOPEN:/tmp/1.sock * * 3) Start typing. The server should repeat the input. */
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);
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 /* * Author: Andrew Rose <hello at andrewrose dot co dot uk> * * Usage: * 1) Prepare cert.pem certificate and privkey.pem private key files. * 2) Launch the server script * 3) Open TLS connection, e.g.: * $ openssl s_client -connect localhost:25 -starttls smtp -crlf * 4) Start testing the commands listed in `cmd` method below. */
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"); }