1. 程式人生 > >epoll實現Reactor模式

epoll實現Reactor模式

轉自:http://blog.csdn.net/analogous_love/article/details/53319815

書上是這麼介紹Reactor模式的:


按照這個思路,我寫個簡單的練習:

  1. /**  
  2.  *@desc:   用reactor模式練習伺服器程式,main.cpp 
  3.  *@author: zhangyl 
  4.  *@date:   2016.11.23 
  5.  */
  6. #include <iostream>
  7. #include <string.h>
  8. #include <sys/types.h>
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11. #include <arpa/inet.h>  //for htonl() and htons()
  12. #include <unistd.h>
  13. #include <fcntl.h>
  14. #include <sys/epoll.h>
  15. #include <signal.h>     //for signal()
  16. #include <pthread.h>
  17. #include <semaphore.h>
  18. #include <list>
  19. #include <errno.h>
  20. #include <time.h>
  21. #include <sstream>
  22. #include <iomanip> //for std::setw()/setfill()
  23. #include <stdlib.h>
  24. #define WORKER_THREAD_NUM   5
  25. #define min(a, b) ((a <= b) ? (a) : (b)) 
  26. int g_epollfd = 0;  
  27. bool g_bStop = false;  
  28. int g_listenfd = 0;  
  29. pthread_t g_acceptthreadid = 0;  
  30. pthread_t g_threadid[WORKER_THREAD_NUM] = { 0 };  
  31. pthread_cond_t g_acceptcond;  
  32. pthread_mutex_t g_acceptmutex;  
  33. pthread_cond_t g_cond /*= PTHREAD_COND_INITIALIZER*/;  
  34. pthread_mutex_t g_mutex /*= PTHREAD_MUTEX_INITIALIZER*/;  
  35. pthread_mutex_t g_clientmutex;  
  36. std::list<int> g_listClients;  
  37. void prog_exit(int signo)  
  38. {  
  39.     ::signal(SIGINT, SIG_IGN);  
  40.     ::signal(SIGKILL, SIG_IGN);  
  41.     ::signal(SIGTERM, SIG_IGN);  
  42.     std::cout << "program recv signal " << signo << " to exit." << std::endl;  
  43.     g_bStop = true;  
  44.     ::epoll_ctl(g_epollfd, EPOLL_CTL_DEL, g_listenfd, NULL);  
  45.     //TODO: 是否需要先呼叫shutdown()一下?
  46.     ::shutdown(g_listenfd, SHUT_RDWR);  
  47.     ::close(g_listenfd);  
  48.     ::close(g_epollfd);  
  49.     ::pthread_cond_destroy(&g_acceptcond);  
  50.     ::pthread_mutex_destroy(&g_acceptmutex);  
  51.     ::pthread_cond_destroy(&g_cond);  
  52.     ::pthread_mutex_destroy(&g_mutex);  
  53.     ::pthread_mutex_destroy(&g_clientmutex);  
  54. }  
  55. bool create_server_listener(constchar* ip, short port)  
  56. {  
  57.     g_listenfd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);  
  58.     if (g_listenfd == -1)  
  59.         returnfalse;  
  60.     int on = 1;  
  61.     ::setsockopt(g_listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));  
  62.     ::setsockopt(g_listenfd, SOL_SOCKET, SO_REUSEPORT, (char *)&on, sizeof(on));  
  63.     struct sockaddr_in servaddr;  
  64.     memset(&servaddr, 0, sizeof(servaddr));   
  65.     servaddr.sin_family = AF_INET;  
  66.     servaddr.sin_addr.s_addr = inet_addr(ip);  
  67.     servaddr.sin_port = htons(port);  
  68.     if (::bind(g_listenfd, (sockaddr *)&servaddr, sizeof(servaddr)) == -1)  
  69.         returnfalse;  
  70.     if (::listen(g_listenfd, 50) == -1)  
  71.         returnfalse;  
  72.     g_epollfd = ::epoll_create(1);  
  73.     if (g_epollfd == -1)  
  74.         returnfalse;  
  75.     struct epoll_event e;  
  76.     memset(&e, 0, sizeof(e));  
  77.     e.events = EPOLLIN | EPOLLRDHUP;  
  78.     e.data.fd = g_listenfd;  
  79.     if (::epoll_ctl(g_epollfd, EPOLL_CTL_ADD, g_listenfd, &e) == -1)  
  80.         returnfalse;  
  81.     returntrue;  
  82. }  
  83. void release_client(int clientfd)  
  84. {  
  85.     if (::epoll_ctl(g_epollfd, EPOLL_CTL_DEL, clientfd, NULL) == -1)  
  86.         std::cout << "release client socket failed as call epoll_ctl failed" << std::endl;  
  87.     ::close(clientfd);  
  88. }  
  89. void* accept_thread_func(void* arg)  
  90. {     
  91.     while (!g_bStop)  
  92.     {  
  93.         ::pthread_mutex_lock(&g_acceptmutex);  
  94.         ::pthread_cond_wait(&g_acceptcond, &g_acceptmutex);  
  95.         //::pthread_mutex_lock(&g_acceptmutex);
  96.         //std::cout << "run loop in accept_thread_func" << std::endl;
  97.         struct sockaddr_in clientaddr;  
  98.         socklen_t addrlen;  
  99.         int newfd = ::accept(g_listenfd, (struct sockaddr *)&clientaddr, &addrlen);  
  100.         ::pthread_mutex_unlock(&g_acceptmutex);  
  101.         if (newfd == -1)  
  102.             continue;  
  103.         std::cout << "new client connected: " << ::inet_ntoa(clientaddr.sin_addr) << ":" << ::ntohs(clientaddr.sin_port) << std::endl;  
  104.         //將新socket設定為non-blocking
  105.         int oldflag = ::fcntl(newfd, F_GETFL, 0);  
  106.         int newflag = oldflag | O_NONBLOCK;  
  107.         if (::fcntl(newfd, F_SETFL, newflag) == -1)  
  108.         {  
  109.             std::cout << "fcntl error, oldflag =" << oldflag << 

    相關推薦

    epoll實現Reactor模式

    轉自:http://blog.csdn.net/analogous_love/article/details/53319815 書上是這麼介紹Reactor模式的: 按照這個思路,我寫個簡單的練習: /**  

    使用c++簡單實現reactor模式

    事件驅動模型廣泛地應用於高效能的web伺服器中。而相對應的事件處理模式,最為典型的就是Reactor模式(中文可以稱作“反應器” “反應堆”等等,各種叫法都不一樣,估且就使用英文吧,叫它Reactor模式)和Proactor模式(中文也稱“主動器” “前攝器”,同前者一樣稱

    Reactor模式epoll

    循環 reactor sched man 存儲 ack oot yep concrete a, Handle表示句柄,文件描述符、socket等;b, EventDemultiplexer表示多路分發機制,調用系統提供的多IO路復用,比如select,epoll。程序先將關

    Reactor模式的.net版本簡單實現--DEMO

    pad ring target current orm 抽象基類 分享 public 其他 近期在學習DotNetty,遇到不少的問題。由於dotnetty是次netty的.net版本的實現。導致在網上敘述dotnetty的原理,以及實現技巧方面的東西較少,這還是

    moduo網路庫的reactor模式(下):實現非阻塞TCP網路

    1、在reactor框架下加入tcp Unix下的tcp連線也是經由socket檔案描述符(sockfd)實現的。此節只是封裝了listening sockefd進行監聽(accept(2)),得到的新連線(普通sockfd)直接提供給使用者讓使用者自行處理。下一節才進一步

    reactor模式C++實現

    copy from github上的一份實現。。。找不到連結了。。。 * epoll主要負責fd到event型別的對映 * EventDemultiplexer管理fd <-> event型別 <-> eventhandler具體怎麼

    Reactor模式簡單實現與理解

    Class Reactor: /** * * 經典的網路服務在每個執行緒中完成對資料的處理: * 但這種模式在使用者負載增加時,效能將下降非常的快。 * 系統執行的效能瓶頸通常在I/O讀寫,包括對埠和檔案的操作上,過去,在打 開一個I/O通道後,

    muduo的reactor模式基本實現

    這幾天一直在看muduo的Eventloop(事件迴圈)這一塊的原始碼,感覺裡面有好多東西例如:智慧指標的使用,將eventfd,timerfd等linux新效能運用進去,C++一些容器的合理使用,還有如何能在多執行緒情況下減少鎖的使用等都是我們應該學習的東西。

    POCO實現reactor模式

    曾經維護維護過一個伺服器專案有用到ACE,也是第一次從中學習到reactor和proactor兩種併發模式,但僅限於用,而且linux上只用reactor,據說是linux系統本身對非同步I/O支援程度等各種因素影響了proactor,關於windows上的ACE應用還得承認

    Python 實現TCP長連線、通訊epoll、select模式

    epoll 是在2.5.44核心中被引進的(epoll(4) is a new API introduced in Linux kernel 2.5.44),它幾乎具備了之前所說的一切優點,被公認為Linux2.6下效能最好的多路I/O就緒通知方法。epoll的優點:1.支援

    【muduo庫學習】實現最簡單的reactor模式

    《linux多執行緒服務端程式設計 使用muduo c++網路庫》的第8章是從0開始講述一個網路庫的實現,比較適合初學者入門。  在本書的第8章中是實現了以下幾個類:eventloop類,poller類,channel類 首先分析channel類的定義: #ifndef M

    利用多線程實現Future模式

    submit design runnable 簡單 接口 ++ array thread 模擬 一、Futrue模式 客戶端發送一個長時間的請求,服務端不需等待該數據處理完成便立即返回一個偽造的代理數據(相當於商品訂單,不是商品本身),用戶也無需等待,先去執行其他的若幹操作

    【Web開發】Mean web開發 01-Express實現MVC模式開發

    http scripts send javascrip 模板引擎 指令 開發環境 depend filter 簡介 Mean是JavaScript的全棧開發框架。更多介紹 用Express實現MVC模式開發是Mean Web全棧開發中的一部分。 Express 是一個基於

    reactor模式與java nio

    time handlers write syn linu pipe accept 事件處理 schmidt ?? Reactor是由Schmidt, Douglas C提出的一種模式,在高並發server實現中廣泛採用。改模式採用事件驅動方式,當事件出現時,後調用對應的

    Ubuntu 16.04安裝VirtualBox 5.1實現無縫模式

    https 1.2 快捷 show 管理 1.0 pkg Coding owin 下載: wget http://download.virtualbox.org/virtualbox/5.1.26/virtualbox-5.1_5.1.26-117224~Ubuntu

    阻塞IO、非阻塞IO、同步IO、異步IO&&Reactor模式

    app sina shu cnblogs 模式 www. htm 同步 ast 3efwzy票僭吩恫越療http://tushu.docin.com/qce8764gnfwar謐浩贅敝客偽http://jz.docin.com/vcqx427mhqxji祭摳嘆頁畔僬http

    實現NAT模式的LVS

    lvs-nat模式實驗:實現NAT模式的LVS環境:先將網咯拓撲圖搭建好,關閉iptables和selinux,在vs服務器上和real server上確定能訪問web服務(httpd)四臺主機,兩臺real server服務器,一臺客戶端機,一臺vs機器 客戶端的地址:1

    實現DR模式的LVS

    lvs和ldirectord實驗:實現DR模式的LVS:環境:五臺主機,一臺客戶端,一臺充當路由器,一臺vs服務器,兩臺rs服務器;網路拓撲圖: 客戶端:外網地址;172.18.77.66 路由器:兩個網卡,內網和外網都有 內網:192.168.77.74 外網:172.18.77.74 vs

    基於keepalived實現多種模式的高可用集群網站架構

    keepalived 一、 實現主從服務器高可用技術。 大概網絡拓撲圖: 前提準備條件: 準備四臺機器,一臺為keepalived的master,一臺為keepalived的backup,一臺為rs1,一臺為rs2,同時都關閉防火墻和selinux。 ①安裝包。 yum install kee

    Ionic3學習筆記(十)實現夜間模式功能

    gpa 效果 app code fff eat ext images provider 本文為原創文章,轉載請標明出處 目錄 創建主題樣式 導入 variables.scss 創建 provider 創建 page 在 App 入口處應用主題 效果圖 1. 創建主題樣式