在此之前,我們對于muduo庫的每一類幾乎都進行了逐行的分析,但是一個網絡庫的每個模塊之間總是有千絲萬縷的關系,所以可能有的地方還是有分析的不到位,所以從這一篇開始,我們從muduo的簡單使用----搭建一個Echo服務器,來一步一步的分析一下整個muduo庫的內在聯系。
TCP網絡編程最本質是的處理三個半事件
連接建立:服務器accept(被動)接受連接,客戶端connect(主動)發起連接
連接斷開:主動斷開(close、shutdown),被動斷開(read返回0)
消息到達:客戶端文件描述符可讀
消息發送完畢:這算半個。對于低流量的服務,可不必關心這個事件;這里的發送完畢是指數據寫入操作系統緩沖區,將由TCP協議棧負責數據的發送與重傳,不代表對方已經接收到數據。
接下來,我們從這幾個事件來梳理整個muduo庫。
搭建Echo服務器
在學習一個網絡庫之前,我們一定是要先學會怎么使用這個網絡庫,接下來,我們搭建一個最簡單的Echo服務器。
什么是Echo服務器
echo服務器,也稱為回顯服務器,簡單來說就是服務端收到什么,就給客戶端發送什么。
源碼
#include <my_muduo/TcpServer.h>
#include <my_muduo/logger.h>#include <string>
#include <functional>class EchoServer
{
public:EchoServer(EventLoop *loop,const InetAddress &addr,const std::string &name):server_(loop,addr,name),loop_(loop){//注冊回調函數server_.setConnectionCallback(std::bind(&EchoServer::onConnection,this,std::placeholders::_1));server_.setMessageCallback(std::bind(&EchoServer::onMessage,this,std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));//設置合適的loop線程數量 loopThreadserver_.setThreadNum(3);}void start(){server_.start();}
private://連接建立或者斷開的回調void onConnection(const TcpConnectionPtr &conn){if(conn->connected()){LOG_INFO("Connection UP : %s",conn->peerAddress().toIpPort().c_str());}else{LOG_INFO("Connection DOWN : %s",conn->peerAddress().toIpPort().c_str());}}//可讀寫事件回調void onMessage(const TcpConnectionPtr &conn,Buffer *buf,TimeStamp time){std::string msg = buf->retrieveAllAsString();conn->send(msg);conn->shutdown(); //關閉寫端EPOLLHUP=> closeCallback}EventLoop *loop_;TcpServer server_;
};int main()
{EventLoop loop;InetAddress addr(8000);//Acceptor non-blocking listenfd create bindEchoServer server(&loop,addr,"EchoServer-01");//listen loopthread listenfd => acceptChannel => mainLoop => subloopserver.start();loop.loop(); //啟動mainloop的底層poolerreturn 0;
}
從代碼中,我們可以看出來它一共做了如下幾件事:
- 創建了一個EventLoop:
EventLoop loop;
,這個EventLoop就是mainLoop,loop就是baseloop_
; - 指定了接收端口號,ip使用默認的127.0.0.1;
- 創建了一個server對象,即TcpServer類對象 :
TcpServer server_;
,并傳入了loop,addr,以及指定了對象名; - 啟動TcpServer服務器,
server.start();
,調用TcpServer::start()
; - 開啟事件循環:
loop.loop();
,調用EventLoop::loop()
。
代碼地址:https://github.com/Cheeron955/mymuduo/tree/master