使用 acl 的生成嚮導快速建立一個C++ WEB 服務器

      在文章《使用 acl 生成嚮導快速建立服務器程序》中介紹如何使用 acl 的服務器生成嚮導自動建立服務器程序的過程,文章《使用 acl_cpp 的 HttpServlet 類及服務器框架編寫WEB服務器程序》介紹了編寫 HTTP 服務器的大致過程,本節將介紹如何使用 acl 提供的生成嚮導快速建立一個 WEB 服務器的過程。在 acl 項目的根目錄下編譯完全部的程序後(運行 make all),而後進入 app/wizard 目錄編譯嚮導程序(運行 make,win32 下可使用 vc2003/vc2008/vc2010 編譯),運行嚮導程序的過程以下:git

 

$./wizard  #運行後向導程序提示以下:
select one below:
m: master_service; d: db; h: http; q: exit

#其中 'm' 表示生成通常性的服務器程序,'h' 表示能夠生成 HTTP 類服務器程序,因此此處選  'h',接着嚮導程序提示輸入所生成的服務器程序的名稱,如可輸入:http_server
please input your program name: http_server

#接着提示 HTTP 應用的類型,目前僅支持自動生成 HTTP 服務,因此只能選擇 's'
please choose one http application type: s
s: http servlet
>s

#接着嚮導程序提示是否須要添加 cookie 的支持,能夠選擇 'y'
Do you want add cookie? y[y/n]: y

#輸入 cookie 名稱
Please enter cookie name: mycookie
create http_server/http_servlet.cpp ok.
#最後提示所採用的服務器模板類型:'t' 表示採用多進程多線程模式,'p' 表示採用多進程模式
choose master_service type:
        t: for master_threads
        p: for master_proc
>t

#嚮導程序便會自動生成如下文件:源文件,工程文件等
create http_server/http_server.cf ok.
create http_server/Makefile.in ok
create http_server/main.cpp ok
create http_server/master_service.h ok
create http_server/master_service.cpp ok
create http_server/http_servlet.h ok
create master_threads ok!
create http_server/Makefile ok.
create http_server/valgrind.sh ok.
create http_server/http_server.sln ok.
create http_server/http_server.vcproj ok.
create http_server/http_server_vc2012.sln ok.
create http_server/http_server_vc2012.vcxproj ok.
create http_server/http_server_vc2012.vcxproj.filters ok.
create http_server/Makefile.in ok
create http_server/stdafx.h ok
create http_server/stdafx.cpp ok
create common_files ok!

       OK,一個簡單的 HTTP 服務器程序就生成了,整個過程不超過 10 秒。由上面顯示能夠看到嚮導生成的文件有:github

 

       一、源程序文件:編程

             main.cpp,stdafx.cpp,master_service.cpp,http_servlet.cpp,windows

             stdafx.h,master_service.h,http_servlet.h瀏覽器

       二、配置文件:http_server.cf服務器

       三、工程文件:Linux 下爲 Makefile.in, Makefile;在 windows 下爲 VC2003 的工程文件(http_server.sln,http_server.vcproj),以及 VC2012 的工程文件(http_server_vc2012.sln,http_server_vc2012.vcxproj,http_server_vc2012.vcxproj.filters)cookie

       四、LINUX 下用來檢測內存泄露的工具腳本:valgrind.sh網絡

 

       在 http_server 目錄下直接運行 make 編譯,即可生成 http_server 可執行程序。該程序既能夠放在 acl_master 服務器框架下運行(生產環境中),又能夠以命令行方式手工直接運行(調試環境下)。爲使瀏覽器能夠直接訪問該 WEB 服務,先打開 main.cpp 文件,將服務器監聽地址(const char* addr)由 「127.0.0.1:8888」 改成 ":8888",而後再 make 從新生成 http_server 程序,手工運行:http_server 提示以下:session

$./http_server alone   # 其中的參數 alone 通知程序以手工方式運行,可參見 main.cpp 中的代碼
listen on: :8888
event_limit: max fdsize: 100001
src/event/events_epoll_thr.c(599), event_epoll_alloc_thr, use thread events - epoll

       而後在瀏覽器輸入該服務器地址:http://192.168.188.112:8888/,獲得的結果以下:多線程

該 XML 文件並未包含任何關聯的樣式信息。文檔樹顯示以下。
---------------------------------------------------------------------
      <root>
             <sessions>
                    <session sid="xxxxxx"/>
             </sessions>
             <params>
                    <param name1="null"/>
                    <param name2="null"/>
             </params>
      </root>

 

        下面爲嚮導程序生成的主要源程序:

        一)、master_service.cpp

         在該文件中,須要關注四個函數:thread_on_accept、thread_on_read、thread_on_timeout、thread_on_close。這四個函數的參數都是 acl::socket_stream* 網絡鏈接流對象。它們被調用的時機爲:

         a、不接收到客戶端鏈接請求時,acl 服務器框架會自動創建與客戶端的鏈接, 同時回調 master_service::thread_on_accept(acl::socket_stream*) 虛函數,應用在此處生成 HTTP 服務器鏈接對象,並將其與 acl::socket_stream* 網絡流關聯:

bool master_service::thread_on_accept(acl::socket_stream* conn) 
{
        logger("connect from %s, fd: %d", conn->get_peer(true),
                conn->sock_handle());
        conn->set_rw_timeout(5);   // 設置客戶端鏈接讀超時時間

        http_servlet* servlet = new http_servlet();   // 建立 HTTP 服務對象
        conn->set_ctx(servlet); // 將該 HTTP 服務對象置入鏈接流中

        return true;
}

         b、當客戶端發來 HTTP 請求時,acl 服務器框架將回調 master_service::thread_on_read(acl::socket_stream*) 虛函數,代碼以下:

bool master_service::thread_on_read(acl::socket_stream* conn)
{
        http_servlet* servlet = (http_servlet*) conn->get_ctx();  // 取出在 thread_on_accept 中設置的 HTTP 服務對象
        if (servlet == NULL)
                logger_fatal("servlet null!");

        // 調用 HTTP 服務過程,若是該函數返回 true 則表示須要與瀏覽器保持長鏈接,不然則告訴服務器框架須要關閉該客戶端鏈接
        return servlet->doRun("127.0.0.1:11211", conn);
}

        c、若是 HTTP 客戶端長時間不發送 HTTP 請求數據,則虛方法:master_service::thread_on_timeout(acl::socket_stream*) 將會由服務器框架調用,該函數若返回 false 則通知服務器框架須要關閉該超時的客戶端鏈接,不然表示繼續等待客戶端發來請求(超時值在 thread_on_accept 中設置)。

        d、當客戶端鏈接超時、客戶端主動關閉鏈接或服務端主動關閉鏈接時,則虛方法 master_service::thread_on_close(acl::socket_stream*) 將由服務器框架調用,代碼以下:

void master_service::thread_on_close(acl::socket_stream* conn)
{
        logger("disconnect from %s, fd: %d", conn->get_peer(),
                conn->sock_handle());

        // 取出在 thread_on_accept 中設置的 HTTP 服務對象,若非空則銷燬之
        http_servlet* servlet = (http_servlet*) conn->get_ctx();
        if (servlet)
                delete servlet;
}

 

        以上四個虛函數很是簡單易懂,但有一點須要注意:這四個虛函數的線程運行空間是不一樣的,thread_on_accept 方法是在服務進程的主線程空間運行的,而其它的三個虛方法則是在線程池中的任一子線程中運行的,且線程空間各不相同,即便對於 thread_on_read 方法,當同一客戶端鏈接對象反覆回調該方法時,其運行的線程空間也多是不一樣的。

 

        在 thread_on_accept 中生成了一個 HTTP 服務類:http_servlet,該類的接口相似於 JAVA 的 HttpServlet 類,使用方法也相似。

        二)、http_servlet.cpp/http_servlet.h

        該類 (http_servlet) 繼承於 acl::http_servlet 類,其須要重載基類的兩個虛方法:doGet/doPost,關於如何使用該類,能夠參考:《用C++實現相似於JAVA HttpServlet 的編程接口》,在此再也不細講。

 

         acl 庫下載:http://sourceforge.net/projects/acl/

         svn:svn checkout svn://svn.code.sf.net/p/acl/code/trunk acl-code

         github:https://github.com/zhengshuxin/acl

         acl 的編譯與使用:http://zsxxsz.iteye.com/blog/1506554

         qq 羣:242722074

       

        文章參考:

         使用 acl::master_threads 類編寫多進程多線程服務器程序

         用C++實現相似於JAVA HttpServlet 的編程接口

         acl 服務器模塊的部署

相關文章
相關標籤/搜索