1. 程式人生 > >Muduo庫的框架剖析及總結(一)

Muduo庫的框架剖析及總結(一)

話說回來呢,前段時間又重新看了一遍Muduo庫,嗯哼,把原來的框架又大概走了一遍,嗯對,僅僅是框架,還有說到最精華的部分,我想說以前我是發過一篇對Muduo庫的執行緒池的剖析(雖然說剖析的一般吧 = =!!!,但是畢竟是自己的心血啊),Muduo庫的記憶體池也是Muduo庫精華的一部分,當然,還有一個精華的部分我認為是Muduo庫的Buffer緩衝區,它運用了環形緩衝區以及vector制動拓長陣列的這一個性質,這裡覺得它運用的很巧妙有木有,WHY?我想說它這裡的環形緩衝區既保持瞭解決黏包問題緩衝區不夠的問題,同時vector又解決了緩衝區自動增長的問題,我想說陳碩在這方面考慮問題簡直就是天才!!!

當然還有什麼bind,function,shareptr,scoreptr,weakptr這些boost庫的東西在Muduo庫中也是巧妙的運用了,誒,陳碩簡直天才,媽蛋啊,把C++簡直運用得爐火純青,淋漓盡致,呃,感覺說了好多屁話吧,接下來開始進入重點!!!

OK,話不多說先上圖(這個沒圖不好表達啊!!)
這裡寫圖片描述

好了好了,我們可以很明顯的從圖上看到我分了幾個部分對吧

TcpServer //代表的是一個總的伺服器的類,我們可以這麼理解它,我們並不知道伺服器內部大概要做什麼,我們只需要呼叫這個TcpServer就可以了,我們可以理解成它是一個伺服器入口吧。
TcpConnection //這裡是一個連線處理器把,能這麼理解吧,當accept接受了一條連線的話就會在這裡面進行處理,嗯哼,就是這樣
Acceptor

//這裡面是對Socket和一個Channel的一個一個封裝,我想理解它為一箇中間的處理器吧,大概能這麼理解吧,當然我們必須把Socket算進來,因為畢竟Acceptor封裝的是Socket
Socket //Socket本身是對socket、listen、bing、accept等伺服器函式進行的一個封裝
Channel //一個時間處理器,會把相關的對可讀可寫的事件處理函式回撥放入這個類中形成一個物件,就是相當於對事件處理方法封裝一下,假如epoll需要處理事件,會從Channel事件處理器中找到相應的方法對事件進行處理
Eventloop //可以理解成為事件分流處理器,把相關的事件處理器Channel註冊金epoll中,而假如epoll有反應則會呼叫Channle中相應的回撥函式,Eventloop底層呼叫的是poll或者epoll
Poll
//只是一個抽象類,作為對呼叫的Epoll或者Poll的基類
EPollPoller //Poll的子類,是呼叫的epoll的一個封裝

我們得把Muduo庫分成四大塊,分別是以Acceptor為主的伺服器塊,TcpConnection的連線塊,Channel的事件塊以及以Eventloop為主的epoll監聽塊。

我們先從Tcpserver來分析一下吧
看下TcpServer中的成員

  EventLoop* loop_;  // the acceptor loop
  const string hostport_;  //埠
  const string name_;  //伺服器名字吧
  boost::scoped_ptr<Acceptor> acceptor_; // avoid revealing Acceptor  一個Acceptor物件
  boost::shared_ptr<EventLoopThreadPool> threadPool_; //執行緒池
  ConnectionCallback connectionCallback_;  //連接回調函式
  MessageCallback messageCallback_;  //連線到資訊的回撥函式
  WriteCompleteCallback writeCompleteCallback_;
  ThreadInitCallback threadInitCallback_;
  AtomicInt32 started_;

當然重要的成員物件我都寫在上面了,有了註釋。
我們再來看看TcpServer的建構函式

TcpServer::TcpServer(EventLoop* loop,
                     const InetAddress& listenAddr,
                     const string& nameArg,
                     Option option)
  : loop_(CHECK_NOTNULL(loop)),
    hostport_(listenAddr.toIpPort()),
    name_(nameArg),
    acceptor_(new Acceptor(loop, listenAddr, option == kReusePort)),
    threadPool_(new EventLoopThreadPool(loop)),
    connectionCallback_(defaultConnectionCallback),
    messageCallback_(defaultMessageCallback),
    nextConnId_(1)
{
  acceptor_->setNewConnectionCallback(
      boost::bind(&TcpServer::newConnection, this, _1, _2));
}

我們可以看到傳進來幾個引數,分別是EventLoop、InetAddress、string、Option
重點還是EventLoopInetAddress,一個是事件分流器,而這個InetAddress呢則是對套接字地址sockaddr_in的一個封裝,我們把埠號和要繫結的IP地址傳進去即可。

EventLoopThreadPool這傢伙是個執行緒池,至於內部的結構希望看我對EventLoopThreadPool分析的那篇文章比較好吧。

TcpServer內部封裝了一個Accepror物件acceptor_,當然我們知道它是用scoped_ptr對它進行封裝的了。

ConnectionCallback connectionCallback_的作用是當accept接受到一個新的連線產生一個新的檔案描述符而創造了一個通訊套接字的時候,呼叫一下這個connectionCallback_回撥函式,當然這個函式內容可以你自己設計,可以讓你提取回調的TcpConnection 物件。

MessageCallback messageCallback_的作用是當通訊套接字接受到一個新的資訊的時候進行回撥,當然,這個回撥函式的內容也可以你自己去設計。

ConnectionCallbackMessageCallback 的回撥函式的引數都有固定格式,在這裡不是重點物件就不說了。

我們可以看到在建構函式中setNewConnectionCallback這個回撥函式呼叫了TcpServer::newConnection,嗯哼,這是一個什麼樣的函式呢?我們來看一下

void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
{
  loop_->assertInLoopThread();
  //從io執行緒池中提取一條工作執行緒出來對accept的通訊socket進行處理
  EventLoop* ioLoop = threadPool_->getNextLoop();
  char buf[32];
  snprintf(buf, sizeof buf, ":%s#%d", hostport_.c_str(), nextConnId_);
  ++nextConnId_;
  string connName = name_ + buf;

  LOG_INFO << "TcpServer::newConnection [" << name_
           << "] - new connection [" << connName
           << "] from " << peerAddr.toIpPort();
  InetAddress localAddr(sockets::getLocalAddr(sockfd));
  // FIXME poll with zero timeout to double confirm the new connection
  // FIXME use make_shared if necessary
  //我們能從這裡看到它實際上是建立了一個TcpConnection,當accept接受到一個新的檔案描述符的時候,建立一個TcpConnection對它進行封裝
   TcpConnectionPtr conn(new TcpConnection(ioLoop,
                                          connName,
                                          sockfd,
                                          localAddr,
                                          peerAddr));
  //我們可以從這裡看出來是對新建立的TcpConnection的一些初始化
  connections_[connName] = conn;
  conn->setConnectionCallback(connectionCallback_);
  conn->setMessageCallback(messageCallback_);
  conn->setWriteCompleteCallback(writeCompleteCallback_);
  conn->setCloseCallback(
      boost::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe
  ioLoop->runInLoop(boost::bind(&TcpConnection::connectEstablished, conn));
}

當然,你可以從這裡看到了啊,這個函式實際上是對accpet新接受到一個通訊套接字以後把它放入到一個新創立的TcpConnection對這個通訊套接字做一個封裝,並將函式指標什麼的初始化,誒對咯,它在最後還呼叫了一個TcpConnection::connectEstablished這個函式,後面介紹到TcpConnection的時候我們會來介紹一下這個函式的作用,在這裡先大概介紹一下這個函式的作用就是將接受到的socket的檔案描述符註冊到epoll事件列表當中,HOHO,就是這樣。

當然TcpServer中還有第二個比較重要的函式,這個函式代表了伺服器的啟動,這個函式當然就是void TcpServer::start()了,我們來簡單的看一下這個函式的程式碼

void TcpServer::start()
{
  if (started_.getAndSet(1) == 0)
  {
  //對執行緒池的一個啟動處理
    threadPool_->start(threadInitCallback_);

    assert(!acceptor_->listenning());
    loop_->runInLoop(
    //當然這是呼叫了底層的listen監聽咯
    boost::bind(&Acceptor::listen, get_pointer(acceptor_)));
  }
}

這個函式啟動了,底層的listen()函式就相當於啟動了,所以我們可以暫時稱這是一個伺服器的開關吧!!!

/********************************************/
呃,總結一就先總結到這裡吧!

相關推薦

Muduo框架剖析總結

話說回來呢,前段時間又重新看了一遍Muduo庫,嗯哼,把原來的框架又大概走了一遍,嗯對,僅僅是框架,還有說到最精華的部分,我想說以前我是發過一篇對Muduo庫的執行緒池的剖析(雖然說剖析的一般吧 = =!!!,但是畢竟是自己的心血啊),Muduo

Muduo框架剖析總結

有些人覺得我的部落格口水話很多,嗯,我個人考慮了一下,可能我寫東西確實沒有那麼高大上,口水話很多,但是我個人確實非常喜歡這種看著非常親切的風格,其實我覺得還好,只要你能讀懂我的部落格就行!!!有問題和意見可以提,有問題可以相互探討、留言,甚至在留言板罵我都行,對

【Java】 Spring 框架初步學習總結簡單實現 IoC 和 AOP

1.0 其中 表示 只需要 第一篇 否則 info fin pojo   Spring 是一個開源的設計層面的輕量級框架,Spring 的好處網上有太多,這裏就不在贅述。   IoC 控制反轉和 AOP 面向切面編程是 Spring 的兩個重要特性。   IoC(Inver

WebKit介紹總結

一 . WebKit 簡介      Webkit 是一個開放原始碼的瀏覽器引擎 (web browser engine) ,最初的程式碼來自 KDE 的 KHTML 和 KJ

muduo框架剖析總結

有些人覺得我的部落格口水話很多,嗯,我個人考慮了一下,可能我寫東西確實沒有那麼高大上,口水話很多,但是我個人確實非常喜歡這種看著非常親切的風格,其實我覺得還好,只要你能讀懂我的部落格就行!!!有問題和意見可以提,有問題可以相互探討、留言,甚至在留言板罵我都行,對我個人也是一

OpenGL在MFC中的使用總結——基本框架

palette 接受 white 要求 無效 結構 del 一次 是你 項目中要畫3D顯示的模型,於是要用到OpenGL,加上是在MFC中,並且是在MFC中的ActiveX中使用。再並且鑒於他們程序主框架的設定。常規的方法還不一定能實現。所以還是查過不少資料,在此一一總

實現自定義查詢的數據設計實現

bre 名稱 審批流程 work 數據庫名 需要 自定義查詢 perm 枚舉 需求 先說一下需求:實現用戶自定義的查詢,用戶可以自定義要查詢的列、自定義條件條件、自定義排序。除了查詢使用外,還可以使用於各個需要根據條件進行約束的業務,如權限; 本設計和實現,很大部分是通過數

2018 - Python 3.7 爬蟲之 Scrapy 框架的安裝配置

一,安裝 Python3.7 二,安裝 pip 三,安裝 pywin32 四,安裝 pyOpenSSL 五,安裝 lxml 六,安裝 zope.interface 七,安裝 twisted 八,安裝 Scrapy 九,一鍵升級所有庫,Python 3.7親測可用,建立

Oracle 技巧總結:行轉列 列裝行

1.行轉列 oracle中行轉列 語法結構select listagg(column1, ',') within group(order by column2) from X;  如下圖所示: listagg(attr1, attr2):第一個引數是要行轉列的那個欄位

基於vue框架專案開發過程中遇到的問題總結

(一)關於computed修改data裡變數的值 問題:computed裡是不能直接修改data裡變數的值,否則在git commit 時會報錯 解決:在computed裡使用get和set來進行獲取和修改data變數,(參考下圖) (二)computed裡監聽陣列

機器學習技法筆記總結SVM系列總結實戰

機器學技法筆記總結(一)SVM系列總結及實戰 1、原理總結 在機器學習課程的第1-6課,主要學習了SVM支援向量機。 SVM是一種二類分類模型。它的基本模型是在特徵空間中尋找間隔最大化的分離超平面的線性分類器。 (1)當訓練樣本線性可分時,通過硬間隔最大化,學習

python序列之元組概念相關函式總結

元組是序列的一種,元組是不可變序列(不能修改,替換),但可進行查詢,增添;元組的建立語法很簡單:用逗號分隔一些值,用圓括號括起來,元組就建立了。 1.先來一個簡單的元組:(圓括號也可以不帶) tou

mybatis框架總結

MyBatis 是一個開源的資料持久層框架。它內部封裝了通過JDBC訪問資料庫的操作,支援普通的SQL查詢、儲存過程和高階對映,幾乎消除了所有的JDBC程式碼和引數的手工設定以及結果集的檢索。MyBatis 作為持久層框架,其主要思想是將程式中的大量SQL語句剝離出來,配置在配置檔案中,實現SQL

android 框架之WIFI系統和系統架構全面總結

知識就本來就是滾雪球,越滾才越大! 在瞭解WIFI模組的系統架構之前。我心中就有一個疑問,那麼android的系統架構是怎樣的呢。其實現在網路中有很多關於android系統架構的描述和解釋,在這裡我不做詳細的研究了,只是貼張圖重新溫故一下。具體細節還要檢視android原始

quartz開源任務排程框架知識總結

1.1.1             JDK Timer & TimerTask 如果是執行簡單的有一定執行週期的,那麼使用jdk自帶的timer是最簡單的。具體: ①、編寫一個簡單類繼承 TimerTask,在這個新編寫的類中重寫父類中run方法,在run中執行要執

集合框架複習總結

最近在複習集合框架,總結一下Java集合框架的一些方法,還只是複習了一部分,就先總結複習了的部分吧。 一、首先,什麼事集合框架?        集合框架是為表示和操作集合而規定的一種統一的標準的體系結構。任何集合框架都包含三大塊內容:對外的介面、介面的實現和對集合運算的演算

2017前端面試題答案總結

1:為何選擇前端這個方向和對前端的理解 為什麼: 第一的話就是對前端很感興趣,之前也接觸過其他的語言,但是直到接觸到前端才發現真的有興趣做下去,興趣是一個人最好的老師, 第二的話前端很有前途,像現在nodejs,rn,微信小程式這類工具和框

常見C++面試題基本知識點總結

原帖:http://www.cnblogs.com/LUO77/p/5771237.html 1. 結構體和共同體的區別。 定義: 結構體struct:把不同型別的資料組合成一個整體,自定義型別。 共同體union:使幾個不同型別的變數共同佔用一段記憶體。 地址

QT 總結1.某位設1或0 2.載入dll、lib 3.char * 轉換為 wchar_t * 4.textBrowser 顯示亂碼 追加 5.checkBox的使能

今天寫小程式遇到的問題,做個小總結: 1.如何對某一位置0或者置1? 寫成巨集,方便移植 #define setbit(x,y) x|=(1<<y) //將X的第Y位置1 #define clrbit(x,y) x&=~(1<<y) //將

VC++6.0&&VS2008&MFC&API學習問題總結(多執行緒CreateThread小問題彙總)

以下資料部分收集於網路,部分是自己碰到的問題(內容將陸續更新): 1、VC++6.0無法設定斷點:先關閉程式,然後刪除目錄下的.opt和.ncb檔案,重新開啟專案,就OK! 2、這個無奈問題折騰了很久,一直以為是資料庫問題,本來是修改的東西,害我把資料庫整體變成了acce