玩轉 PHP 網路程式設計全套之 libevent 框架首篇

勺顛顛發表於2020-04-25

LIBEVENT框架

此框架的擴充套件是LIBEVENT,php手冊地址libevent,該框架了封裝I/O事件,定時事件,中斷訊號事件,核心I/O複用函式支援EPOLL,POLL,SELECT,DEVPOLL,KQUEUE。框架官方網站libvent官網以下專案使用了該框架

玩轉 PHP 網路程式設計全套之 libevent 框架

框架涉及到的知識點說明【非常重要,否則可能會複製貼上跑起來了,但是相關知識點並沒有完全的理解,更談不上熟悉php擼的workerman框架了^_^】

  • TCP/IP
  • thread 執行緒
  • I/O複用
  • 事件處理模式
    • reactor 模式
    • Proactor 模式
  • 併發模式
    • 半同步/半非同步模式
  • 定時器
  • 中斷訊號
  • I/O事件
  • 事件多路分發器EventDeumultiplexer
  • 事件處理器EventHandler
  • 低層知識
    • 網路卡驅動
    • ARP協議【mac硬體實體地址交換】
    • 網路資料幀
  • 同步/非同步執行緒

本人註解的網路框架libevent原始碼核心原理分析
相關測試原始碼和分析流程以及筆記可聯絡本人獲取

原始碼框架安裝說明

php libevent擴充套件安裝地址

玩轉 PHP 網路程式設計全套之 libevent 框架

如果認真看過PHP手冊的人安裝php擴充套件是非常容易的.
本人安裝的擴充套件是event2.2.1版本
玩轉 PHP 網路程式設計全套之 libevent 框架

執行個示例玩先

<?php  class MyListenerConnection {     private $bev, $base;      public function __destruct() {         //將讀寫和異常回撥清空同時釋放BufferEvent相關內建的資料         $this->bev->free();     }     public function __construct($base, $fd) {         $this->base = $base;          //建立BufferEvent物件         //此物件內建了讀寫事件處理器,但並沒有新增到I/O事件池中         //同時該物件分別建立input/outpu物件【內建建立】主要用於資料讀寫【接收和傳送】         $this->bev = new EventBufferEvent($base, $fd, EventBufferEvent::OPT_CLOSE_ON_FREE);          //設定讀寫異常回撥函式 【寫回撥並未設定】         $this->bev->setCallbacks(array($this, "echoReadCallback"), NULL,             array($this, "echoEventCallback"), NULL);          //將內建的寫事件處理器新增到I/O事件池中,並且向核心事件表註冊讀就緒事件         if (!$this->bev->enable(Event::READ)) {             echo "Failed to enable READ\n";             return;         }     }     public function echoReadCallback($bev, $ctx) {         //讀就緒事件發生後,內建的讀事件處理器執行,然後執行此函式         //同時呼叫output,並把input【內建的讀事件處理器讀取的資料會放入到此input物件中】         //直接將接受的資料寫入到客戶端         $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) {         //建立event_base物件         //內建了I/O事件處理器池和訊號事件處理器池         //同時也內建的定時時間堆         $this->base = new EventBase();         if (!$this->base) {             echo "Couldn't open event base";             exit(1);         }          //建立socket 並監聽同時將此socket的讀就緒事件註冊到【經過I/O複用函式即事件多路分發器EventDemultiplexer管理】         //此socket 內建了監聽事件處理器,客戶端連線後,會呼叫此事件處理器,然後再執行使用者設定的回撥函式acceptConnCallBack函式         //EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE 標誌位         //EventListener::OPT_CLOSE_ON_FREE 此引數會關閉低層連線socket         //EventListener::OPT_REUSEABLE 和前面說過的socket 選項有關【不清楚請翻閱之前我寫過的東西】         //後面2個引數為ip和埠用於生成socket         $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);         }          //設定此socket事件處理器的錯誤回撥         $this->listener->setErrorCallback(array($this, "accept_error_cb"));     }      public function dispatch() {         //內建了event_base_loop進行迴圈處理         //主要是呼叫如epoll的epoll_wait函式進行監聽         //當任意I/O產生了就緒事件則會通知此程式         //此程式將會遍歷就緒的I/O事件讀取檔案描述符         //並從I/O事件處理器池讀取對應的事件處理器隊鏈         //再將事件處理器插入到請求佇列中         //兩從請求佇列中獲取到事件並迴圈一一處理         //從而執行指定的回撥函式         $this->base->dispatch();     }      /**      * @param $listener 上面的監聽器      * @param $fd 產生就緒事件的檔案描述符      * @param $address 客戶端地址      * @param $ctx 使用者自定義傳遞的引數      */     public function acceptConnCallback($listener, $fd, $address, $ctx) {          $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 = 12345;  if ($argc > 1) {     $port = (int) $argv[1]; } if ($port <= 0 || $port > 65535) {     exit("Invalid port"); }  $l = new MyListener($port); //event_base_loop持續阻塞 //直到核心事件表中的I/O事件就緒產生才會執行相就的回撥函式 $l->dispatch(); 

玩轉 PHP 網路程式設計全套之 libevent 框架

框架內部用到的資料結構和PHP關聯的物件

new EventBase() 對應c內部的event_base結構體   new EventListener 對應內部的evconnlistener結構體   new EventBufferEvent 對應內部的bufferevent結構體   更多相關的內容請閱讀本人註解的核心libevent框架,不然你可能對這些知識點感到燒腦子   
本作品採用《CC 協議》,轉載必須註明作者和本文連結

只會php crud的渣渣

相關文章