evpp是奇虎360內部使用的開源多線程網絡庫,集tcp/udp/http多種協議的服務器和客戶端支持。github代碼路徑是:https://github.com/Qihoo360/evpp,可以不依賴boost庫,使用現代c++14語言(evpp/invoke_timer.cc的lambda表達式使用到了c++14的特性)進行編碼。本項目高度參考了muduo網絡庫,而底層使用現成的libevent庫作爲事件驅動庫,典型的一個reactor網絡編程模式的例子,本文就是通過分析evpp源碼來達到學習c++網絡編程的效果。
muduo代碼我也拜讀過,muduo有個特點,它完全是爲linux而寫的(譬如裏面用到了eventfd,timerfd以及epoll等,都是linux系統特有的,而且還跟linux版本有關,系統版本太低也不支持,譬如eventfd),而evpp做了一定的平臺兼容性,能一定程度做到支持windows平臺,得益於libevent庫。另外,木鐸有個base庫,是重複造輪子了,其他還好,也是一個不可多得的多線程網絡服務器編程demo,值得參考,而evpp沒有像muduo那樣重新實現一套基礎庫(如線程庫、互斥鎖、條件變量等),而是利用了c++14自帶的std::thread、std::mutex等,相對通用很多,而且學習這些類庫使用在其他項目也能用得着,畢竟是c++的標準類庫。
摘抄了github上的說明,大家可以點進去前文給出的github路徑閱讀Readme:
我們先給出基礎的TCP服務器和客戶端的例子,http的話我就不講解了。
TCP服務器端例子:
#include <evpp/tcp_server.h>
#include <evpp/buffer.h>
#include <evpp/tcp_conn.h>
int main(int argc, char* argv[]) {
std::string addr = "0.0.0.0:9099";
int thread_num = 4;
evpp::EventLoop loop;
evpp::TCPServer server(&loop, addr, "TCPEchoServer", thread_num);
server.SetMessageCallback([](const evpp::TCPConnPtr& conn,
evpp::Buffer* msg) {
LOG_INFO << "SetMessageCallback string: " << msg->ToString() << LOG_LR;
conn->Send(msg);
});
server.SetConnectionCallback([](const evpp::TCPConnPtr& conn) {
if (conn->IsConnected()) {
LOG_INFO << "A new connection from " << conn->remote_addr() << LOG_LR;
} else {
LOG_INFO << "Lost the connection from " << conn->remote_addr() << LOG_LR;
}
});
server.Init();
server.Start();
loop.Run();
return 0;
}
而TCP客戶端例子:
#include <evpp/tcp_client.h>
#include <evpp/buffer.h>
#include <evpp/tcp_conn.h>
int main(int argc, char* argv[]) {
std::string addr = "127.0.0.1:9099";
if (argc == 2) {
addr = argv[1];
}
evpp::EventLoop loop;
evpp::TCPClient client(&loop, addr, "TCPPingPongClient");
client.SetMessageCallback([&loop, &client](const evpp::TCPConnPtr& conn,
evpp::Buffer* msg) {
LOG_TRACE << "Receive a message [" << msg->ToString() << "]" << LOG_LR;
client.Disconnect();
});
client.SetConnectionCallback([](const evpp::TCPConnPtr& conn) {
if (conn->IsConnected()) {
LOG_INFO << "Connected to " << conn->remote_addr() << LOG_LR;
conn->Send("hello");
} else {
conn->loop()->Stop();
}
});
client.Connect();
loop.Run();
return 0;
}
看得出來類的使用跟muduo如出一轍,也是拋棄c++的繼承,積極使用"std::function+std::bind"兩兄弟。作者也是致敬了一番muduo庫。