在文章《使用 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 类编写多进程多线程服务器程序