goahead(web服务器)分析

一、参考网址

  1、源码的github地址

  2. demo示例(github)goahead2.5

  3. GoAhead的asp过程与goform过程浅析

二、网页是采用文件读写方式,还是转换为数组方式?

  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

posted @ 2019-10-15 10:25  shanyu20  阅读(1429)  评论(0编辑  收藏  举报