goahead(web服务器)分析
一、参考网址
2. demo示例(github)goahead2.5
二、网页是采用文件读写方式,还是转换为数组方式?
1)其通过宏定义“WEBS_PAGE_ROM”来区分,我是在websPageReadData()(page.c)函数源码发现的
int websPageReadData(webs_t wp, char *buf, int nBytes) { #ifdef WEBS_PAGE_ROM a_assert(websValid(wp)); return websRomPageReadData(wp, buf, nBytes); #else a_assert(websValid(wp)); return read(wp->docfd, buf, nBytes); #endif }
2) 其保存网页的数组定义:websRomPageIndexType websRomPageIndex[], 其内部有个Page成员指向网页数组数据:
/* * Compiled Rom Page Index */ typedef struct { char_t *path; /* Web page URL path */ unsigned char *page; /* Web page data */ int size; /* Size of web page in bytes */ int pos; /* Current read position */ } websRomPageIndexType;
3) websRomPageIndex[]数组初始化过程
websRomOpen()
symEnter(romTab, name, valueInteger((int) wip), 0); //填充到sym[romTab]中
4) 从数组中读出网页的过程:
websDefaultHandler 注册了写事件处理
websDefaultWriteEvent
websPageReadData
websRomPageReadData
2、输入URL时,其默认网页定义
在initwebs()函数中有UrlHandlerDefine(T("/"), NULL, 0, websHomePageHandler, 0);
其websHomePageHandler()定义如下:
static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, char_t *url, char_t *path, char_t *query) { /* * If the empty or "/" URL is invoked, redirect default URLs to the home page */ if (*url == '\0' || gstrcmp(url, T("/")) == 0) { websRedirect(wp, T("home.asp")); return 1; } return 0; }
3、浏览器提交的数据处理流程
initWebs() (main.c)
websOpenServer(port, retries);
websOpenListen(port, retries);
socketOpenConnection(NULL, port, websAccept, 0); 中的websAccept
int websAccept(int sid, char *ipaddr, int port, int listenSid)
socketCreateHandler(sid, SOCKET_READABLE, websSocketEvent, (int) wp);
static void websSocketEvent(int sid, int mask, int iwp)
void websReadEvent(webs_t wp)
websUrlHandlerRequest(wp)
sp = &websUrlHandler[i]; 其数组内容由websUrlHandlerDefine()函数填充
if ((*sp->handler)(wp, sp->urlPrefix, sp->webDir, sp->arg,
wp->url, wp->path, wp->query))
int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
char_t *url, char_t *path, char_t *query)
sp = symLookup(formSymtab, formName);// formSymtab数组内容由websFormDefine()函数填充
fn = (int (*)(void *, char_t *, char_t *)) sp->content.value.integer;
(*fn)((void*) wp, formName, query); 最后的表单处理函数,
4、对浏览器提交的数据处理,移植需要注意的两步(即最后两步)
1)先由websUrlHandlerDefine(T("/goform"), NULL, 0, websFormHandler, 0);中注册的websFormHandler()函数处理
其内部有怎么一段:fn = (int (*)(void *, char_t *, char_t *)) sp->content.value.integer;
(*fn)((void*) wp, formName, query);
1 int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 2 char_t *url, char_t *path, char_t *query) 3 { 4 printf("formhandler %s ----- %d\n", __func__, __LINE__); 5 sym_t *sp; 6 char_t formBuf[FNAMESIZE]; 7 char_t *cp, *formName; 8 int (*fn)(void *sock, char_t *path, char_t *args); 9 10 a_assert(websValid(wp)); 11 a_assert(url && *url); 12 a_assert(path && *path == '/'); 13 14 websStats.formHits++; 15 16 /* 17 * Extract the form name 18 */ 19 gstrncpy(formBuf, path, TSZ(formBuf)); 20 printf("path:%s\n", path); 21 printf("formbuf:%s\n", formBuf); 22 if ((formName = gstrchr(&formBuf[1], '/')) == NULL) { 23 websError(wp, 200, T("Missing form name")); 24 return 1; 25 } 26 //printf("111formname:%s\n", formName); 27 formName++; 28 //printf("222formname:%s\n", formName); 29 #if 1 30 if ((cp = gstrchr(formName, '/')) != NULL) //后续"/"之后的都失效 31 { 32 *cp = '\0'; 33 } 34 #endif 35 //printf("333formname:%s\n", formName); 36 /* 37 * Lookup the C form function first and then try tcl (no javascript support 38 * yet). 39 */ 40 sp = symLookup(formSymtab, formName); 41 if (sp == NULL) { 42 websError(wp, 200, T("Form %s is not defined"), formName); 43 } else { 44 fn = (int (*)(void *, char_t *, char_t *)) sp->content.value.integer; 45 a_assert(fn); 46 if (fn) { 47 /* 48 * For good practice, forms must call websDone() 49 */ 50 (*fn)((void*) wp, formName, query); 51 52 /* 53 * Remove the test to force websDone, since this prevents 54 * the server "push" from a form> 55 */ 56 #if 0 /* push */ 57 if (websValid(wp)) { 58 websError(wp, 200, T("Form didn't call websDone")); 59 } 60 #endif /* push */ 61 } 62 } 63 return 1; 64 }
2) 然后根据URL中判断是哪个表单,然后调用相应的在initWebs()函数中用websFormDefine()注册的回调函数:
如:websFormDefine(T("gpio_p24"), on_gp24_set); 则表示URL中末尾是gpio_p24,则调用on_gp24_set()函数
int websFormDefine(char_t *name, void (*fn)(webs_t wp, char_t *path, char_t *query)) { //1 printf("formdefine %s ----- %d\n", __func__, __LINE__); a_assert(name && *name); a_assert(fn); if (fn == NULL) { return -1; } symEnter(formSymtab, name, valueInteger((long) fn), 0); return 0; }
3