使用C++编写Apache模块教程

在许多关于Apache模块开发的资料中,关于Perl语言的介绍比比皆是,而C++的内容却寥寥无几。本文旨在填补这一空白,介绍如何使用C++构建Apache模块。 必须指出的是,无法完全避开C语言,因为Apache和APR都是用C语言编写的,也将使用C语言来与之接口。目标是将其封装起来,使应用程序可以完全用C++编写。

开发环境搭建

所有项目都需要一个起点。因此,让花些时间来搭建开发环境。首先,这些文章主要针对基于*nix的用户(如Linux、FreeBSD等)。如果是微软Windows用户,这里也有足够的信息让开始,但前提是已经是一个经验丰富的微软开发者。这里描述的一切都是基于基于CentOS6的开发系统。

在设置中,有一个运行CentOS6的专用服务器,也可以使用虚拟机。CentOS6服务器还安装了X-Window。 对于实际的开发,使用一台运行Microsoft Windows 7的笔记本电脑。安装了Putty和Xming,这让可以直接在Windows桌面上打开各种工具。然而,*nix的纯粹主义者也可以只使用一台机器,如果他们喜欢的话。

首先,需要确保服务器配置了所有需要的软件包。在CentOS6上,使用yum安装了以下软件包: yum groupinstall 'Development Tools' httpd-2.2.15-15.el6.centos.1.x86_64 httpd-devel-2.2.15-15.el6.centos.1.x86_64 httpd-tools-2.2.15-15.el6.centos.1.x86_64 注意 - 如果使用的是32位机器,请确保加载了正确的32位软件包。

接下来,从安装Netbeans用于C/C++,并将其安装到服务器上。可能还需要安装Java运行时包,因为Netbeans使用它。 如果在服务器上本地运行,现在应该能够打开Netbeans。然而,如果像一样在Microsoft Windows上,将想要安装Putty和Xming。设置Putty以允许X-Forwarding。一旦通过SSH连接到服务器,运行Netbeans应该会将IDE显示在Microsoft Windows桌面上的一个漂亮的Xming窗口中。

此时,可以创建一个标准的helloworld.c项目,只是为了测试工具链,并确保一切正常工作。

第一个Apache模块,HelloWorld

如果对Apache模块开发完全不熟悉,那么阅读标准的Apache helloworld教程是一个很好的开始。应该花几分钟熟悉这个教程,因为这正是将以C/C++格式实现的。记住,无法逃避C语言,但可以很好地将其隐藏在封装的对象中。所以,一旦看过Apache教程,就回到这里,将开始。

让从创建Netbeans项目开始。从文件 > 新建项目开始,选择C/C++,项目类型应该是C/C++动态库,如下图所示:

在下一个屏幕上,输入了“mod_foo”作为项目名称,而不是“helloworld”,因为将在未来的文章中使用这个项目。 所以现在有一个准备开始的裸项目。但首先需要设置一些项目偏好,然后构建一个合理的文件系统布局。首先是布局:

假设在自己的工作目录中,转到项目: cd NetBeansProjects/mod_foo mkdir src mkdir include 布局应该看起来像这样:

现在在项目上右键单击,选择弹出上下文菜单底部的属性。选择“链接器”,然后选择“输出”。默认的Netbeans使用的是将输出称为“libmod_foo”,想将其更改为“mod_foo”,如下所示:

接下来选择C编译器,在包含目录中输入以下内容: include [见注释1] /usr/include/httpd /usr/include/apr-l /usr/local/include /usr/include [1]注意,这是作为“相对”包含添加的,选择上面创建的目录。其余的都是系统目录,应该在服务器上是标准的。这里有一张图表显示了这些添加:

到目前为止都很好,但请注意,到目前为止配置的是“Debug (active)”构建配置。当构建Release版本时,将不得不重复这个,并添加Release构建配置的属性。

观察敏锐的人会从图片中注意到,这样做的时候是以root用户登录的,而不是普通账户。主要原因是稍后会看到它确实使调试事情变得更容易。但这里有一个警告,使用开发系统上的root账户是一个安全风险。确保开发系统在防火墙后面,并且物理上也得到了很好的保护(是的,当在厕所的时候,老板颠倒了所有的屏幕,只是为了证明一个观点!)。

在开始编写代码之前,有一件事应该在Netbeans项目上做。将创建类对象,封装Apache和APR接口。为了构建项目并使其更清晰,将使用Netbeans的“逻辑”文件夹创建一个"Apache"目录。在这里,将放置所有与Apache交互的对象。在“源文件”和“头文件”中都这样做。还添加了应用程序的逻辑文件夹,以将纯C++应用程序代码与Apache封装代码分开。有关更多详细信息,请参见这些图片:

现在是时候创建前两个文件,mod_foo.cpp和mod_foo.hpp,它们应该在源文件和头文件的“根”文件夹中创建。确保指定了之前制作的文件夹(src或include):

最后应该有类似这样的东西:

现在可以开始构建Apache的“样板”代码,并添加一些其他东西,使C++链接工作得很好。

这里是这两个文件:

#ifndef MOD_FOO_HPP #define MOD_FOO_HPP #ifdef __cplusplus #define EXTERN_C_BLOCK_BEGIN extern "C" { #define EXTERN_C_BLOCK_END } #define EXTERN_C_FUNC extern "C" #else #define EXTERN_C_BLOCK_BEGIN #define EXTERN_C_BLOCK_END #define EXTERN_C_FUNC #endif #include <httpd.h> #include <http_protocol.h> #include <http_config.h> #endif /* MOD_FOO_HPP */ #include "mod_foo.hpp" EXTERN_C_FUNC int foo_handler( request_rec* inpRequest ) { int nReturnVal = DECLINED; if (inpRequest->handler != NULL && strcmp(inpRequest->handler, "foo") == 0) { ap_rputs("Hello World from FOO", inpRequest); nReturnVal = OK; } return nReturnVal; } EXTERN_C_FUNC void foo_hooks( apr_pool_t* inpPool ) { ap_hook_handler( foo_handler, NULL, NULL, APR_HOOK_MIDDLE ); } EXTERN_C_BLOCK_BEGIN module AP_MODULE_DECLARE_DATA foo_module = { STANDARD20_MODULE_STUFF, NULL, NULL, NULL, NULL, NULL, foo_hooks }; EXTERN_C_BLOCK_END

所以,在Netbeans中可以通过按F11来构建这个,如果一切顺利,将得到一个成功的构建。现在是时候安装模块并给它的第一个测试运行。

在ssh shell中改变目录到Netbeans构建模块的地方。在服务器上它在这里:~/NetBeansProjects/mod_foo/dist/Debug/GNU-Linux-x86/。在那里应该看到一个名为mod_foo.so的文件,可以将其安装到Apache中。注意,如果ssh shell不是root,将需要root权限来做到这一点: # apxs –n foo –I mod_foo.so Apache的apxs工具应该作为Apache安装的一部分被安装。对于标准的64位服务器,这将把mod_foo.so安装到/usr/lib64/httpd/modules/。

现在模块已经就位,需要激活它。在/etc/httpd/conf.d中创建一个名为foo.conf的新文件,并在其中放置: LoadModule foo_module modules/mod_foo.so <Location /foo> SetHandler foo </Location>

最后,要以单进程/非线程模式运行Apache,使用httpd –X调用,这将导致Apache运行直到用Ctrl-C杀死它,然后指向最喜欢的Firefox ,如果一切正常,应该看到"Hello World from FOO"打印出来。

调试

在继续编写一些不错的OOPs代码之前,值得一提如何使用Netbeans中集成的gdb调试器。显然,不会尝试在Netbeans中构建整个Apache并从那里运行它(尽管可以)。

最简单的方法是使用Netbeans的“Attach to process”在Debug菜单下。在弹出对话框中输入"httpd –X"进行过滤,将看到从命令行启动的进程。选择它并附加。然后可以在foo_handler()函数中设置一个断点。当刷新Firefox时,它将在那个点中断。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485