goahead webserver源码分析 下载本文

内容发布更新时间 : 2024/5/18 4:11:05星期一 下面是文章的全部内容请认真阅读。

goahead webserver源码分析

(2010-01-17 10:12:16) 标签: 杂谈

1.一个txt文本架构图 main() |

|--websOpenServer() | |-- websOpenListen()

| |--socketOpenConnection() | |--打开webServer服务器

| |--初化socket_t结构(注册websAccept()回调函数(socket_t sp->accept= websAccept)等)

| |--把socket_t结构加入数组socketList | |

|--websUrlHandlerDefine()

| |--初始化websUrlHandlerType结构的websUrlHandler数组

| |--将urlPrefix和回调函数绑定在websUrlHandler[websUrlHandlerMax]中 |

|--websUrlHandlerDefine(websDefaultHandler)

| |--初始化websUrlHandlerType结构的websUrlHandler数组

| |--将urlPrefix和回调函数绑定在websUrlHandler[websUrlHandlerMax]中 | | |

|--websFormDefine()

| |--初始化symbol table结构sym_t,把名字和回调函数名放进sym_t结构 | |--把sym_t结构放进hash表中 |

|--websAspDefine()

| |--初始化symbol table结构sym_t,把名字和回调函数名放进sym_t结构 | |--把sym_t结构放进hash表中 | |

|(main loop)

----|--socketReady(-1) || socketSelect(-1, 1000)

^ |--轮询socketList |--轮询socketList中的handlerMask | | |--中的几个变量 |--改变socketList中的currentEvents | |

| |--socketProcess()

^ | |--轮询socketList[] | | |--socketReady() | | |--socketDoEvent()

| | |--如果有新的连接(来自listenfd)就调用socketAccept() | | |--调用socketAlloc()初始化socket_t结构 | | |--把socket_t结构加入 socketList数组 | | |--调用socket_t sp->accept()回调函数 | |

| | |--如果不是新的连接就查找socketList数组调用socket_t sp->handler()回调函数

| | | | --|

websAccept() |--做一些检查

|--socketCreateHandler(sid, SOCKET_READABLE, websSocketEvent, (int) wp) | |--把sid注册为读事件,初始化socket_t sp->handler = websSocketEvent等, 更新对应的socketList数组(handlerMask值等)

websSocketEvent() |--判断读写操作 |--读websReadEvent()

| |--websUrlHandlerRequest()

| |--查找wbsUrlHandler数组,调用和urlPrefix对应的回调函数(websFormHandler(),websDefaultHandler()等)

|

|--写,调用(wp->writeSocket)回调函数

websFormHandler()

|--跟据formName查找hash表,调用用户定义的函数

websDefaultHandler()

|--处理默认的URL请求,包括asp页面 |--websSetRequestSocketHandler()

| |--注册默认的写事件函数wp->writeSocket = websDefaultWriteEvent

| |--socketCreateHandler(wp->sid, SOCKET_WRITABLE, websSocketEvent, (int) wp)

| |--把sid注册为写事件,初始化socket_t sp->handler = websSocketEvent等, 更新对应的socketList数组

websDefaultWriteEvent() |

|--写数据,不包括asp页面

2.跟着main走

Main函数很简短,所以可以对他的代码进行一行一行注释,如下: int main(int argc, char** argv) {

bopen(NULL, (60 * 1024), B_USE_MALLOC);

signal(SIGPIPE, SIG_IGN);

if (initWebs() < 0) { return -1; }

#ifdef WEBS_SSL_SUPPORT websSSLOpen(); #endif

while (!finished) {

if (socketReady(-1) || socketSelect(-1, 1000)) {

socketProcess(-1); }

websCgiCleanup();

emfSchedProcess(); }

#ifdef WEBS_SSL_SUPPORT websSSLClose(); #endif

#ifdef USER_MANAGEMENT_SUPPORT umClose(); #endif

websCloseServer(); socketClose(); #ifdef B_STATS memLeaks(); #endif bclose(); return 0; }

3.一些想法

1, 找出他们共同的数据结构

2, 找出对这些数据结构维护(操作)的函数

3, 从http的get或者是post流程来看程序 4, 整体架构如何掌握

5, 分模块,从全局的角度看各个模块的功能 6, 从main函数起,按树型结构一层层分析下去

选择第五种方法:

1, sock模块,专门处理网络链接这一块,有这么几个文件:

sock.c和sockGen.c,sock.c是(维护)处理链接的socket_t数据结构,sockGen.c是(维护)处理链接的。

2, 对http协议数据进行操作(读取和分析),webc.c文件 3, 对具体数据的操作(asp,form…),handler.c文件

选择第三种方法来看程序:

假设有个http请求:从这个http请求到服务器的处理,然后返回这样一个过程来看goahead是怎么操作的?

1,写一个http请求的url和一个head 1, 写一个http请求的post的head 注:

因为这次要看通整个goahead代码,所以一下子不知道以什么思路来看。上面是一些想法,不知道从哪里开始分析一个项目的代码,也不知道取舍哪些进行程序结构和功能方面的分析。后来的结果是写出了下面的文字。

4.goahead mainloop源码分析

4.1 socketReady(-1)函数分析

socketReady函数检查已建立连接的socket中是否有以下事件,如果检查到一个,就返回1,如果没有检查到,就返回零。

(1) sp->flags & SOCKET_CONNRESET,如果该socket的flag标志为SOCKET_CONNRESET(该标志在哪里设置(初始化)的?),则调用函数socketCloseConnection(该函数后面会解释)关闭该socket连接,然后返回0;

(2) sp->currentEvents & sp->handlerMask,如果该socket当前的事件和他要处理的事件相同,就返回1,告诉调用socketReady的函数有socket准备好被处理了; (3) sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0,如果该socket要处理的事件是SOCKET_READABLE并且该socket的缓存中有可读的数据,