LIBEVENT框架
此框架的擴充套件是LIBEVENT,php手冊地址libevent,該框架了封裝I/O事件,定時事件,中斷訊號事件,核心I/O複用函式支援EPOLL,POLL,SELECT,DEVPOLL,KQUEUE。框架官方網站libvent官網以下專案使用了該框架
框架涉及到的知識點說明【非常重要,否則可能會複製貼上跑起來了,但是相關知識點並沒有完全的理解,更談不上熟悉php擼的workerman框架了^_^】
- TCP/IP
- thread 執行緒
- I/O複用
- 事件處理模式
- reactor 模式
- Proactor 模式
- 併發模式
- 半同步/半非同步模式
- 定時器
- 中斷訊號
- I/O事件
- 事件多路分發器EventDeumultiplexer
- 事件處理器EventHandler
- 低層知識
- 網路卡驅動
- ARP協議【mac硬體實體地址交換】
- 網路資料幀
- 同步/非同步執行緒
本人註解的網路框架libevent原始碼核心原理分析
相關測試原始碼和分析流程以及筆記可聯絡本人獲取
原始碼框架安裝說明
如果認真看過PHP手冊的人安裝php擴充套件是非常容易的.
本人安裝的擴充套件是event2.2.1版本
執行個示例玩先
<?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關聯的物件
new EventBase() 對應c內部的event_base結構體 new EventListener 對應內部的evconnlistener結構體 new EventBufferEvent 對應內部的bufferevent結構體 更多相關的內容請閱讀本人註解的核心libevent框架,不然你可能對這些知識點感到燒腦子
本作品採用《CC 協議》,轉載必須註明作者和本文連結