在文章《使用 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 類編寫多進程多線程服務器程序