• LightHttpd源码分析


    源码:https://github.com/EZLippi/Tinyhttpd

    要在Linux中编译,无需像代码注释所说那样:

    /* This program compiles for Sparc Solaris 2.6.
    * To compile for Linux:
    * 1) Comment out the #include <pthread.h> line.
    * 2) Comment out the line that defines the variable newthread.
    * 3) Comment out the two lines that run pthread_create().
    * 4) Uncomment the line that runs accept_request().
    * 5) Remove -lsocket from the Makefile.
    */

    直接编译即可。

    编译,有警告:

    httpd.c:282: warning: not enough variable arguments to fit a sentinel

    对应代码:

    execl(path, NULL);

    解决办法:添加一个参数NULL,即修改为:

    execl(path, NULL, NULL);

    主要函数一览:

    bad_request: 返回给客户端这是个错误请求,HTTP 状态吗 400 BAD REQUEST.
    cat: 读取服务器上某个文件写到 socket 套接字。
    cannot_execute: 主要处理发生在执行 cgi 程序时出现的错误。
    error_die: 把错误信息写到 perror 并退出。
    execute_cgi: 运行 cgi 程序的处理,也是个主要函数。
    get_line: 读取套接字的一行,把回车换行等情况都统一为换行符结束。
    headers: 把 HTTP 响应的头部写到套接字。
    not_found: 主要处理找不到请求的文件时的情况。
    sever_file: 调用 cat 把服务器文件返回给浏览器。
    startup: 初始化 httpd 服务,包括建立套接字,绑定端口,进行监听等。
    unimplemented: 返回给浏览器表明收到的 HTTP 请求所用的 method 不被支持
     
     
     
    函数main():
    1. 调用 startup()创建TCP服务器监听套接字 server_sock。
    2. 无限循环 反复执行
      1. 接受客户端连接:调用 accept()
      2. 创建处理线程:调用 pthread_create()
    3. 关闭 server_sock。
    4. 结束。■
     
      
    函数accept_request(client):处理一个HTTP请求。
    1. 从连接套接字client读入下一行至buf(以 、 或 结尾的串):调用 get_line()。
    2. 从buf取请求方法至method
    3. 若方法不是"GET"也不是"POST",则发送“方法未实现”的响应;结束。■
    4. 若方法是"GET",则寻找'?';若有,则取其后的查询参数到query_string,并置CGI标志cgi为1。
    5. 从buf取请求路径至url
    6. 把url串接到 "htdocs"后面,得到path,例如:htdocs/dir/file1.html
    7. 若path以'/'结尾,则自动接上默认文档名 "index.html"
    8. 判断path的文件类型:调用stat()
    9. 若文件不存在,则
      1. 从client读入并丢弃头部
      2. 发送响应:文件未找到
      3. 结束。■
    10. 若path是目录,则 path后面接上 "/index.html"
    11. 若path可执行,则置cgi为1
    12. 如果是cgi,则执行之:调用 execute_cgi()
    13. 否则发送文件:调用 serve_file()
    14. 关闭client,结束。■
     
    小结:
    此函数中首先解析客户端的请求方式,是GET,还是POST。tinyhttpd只能处理这2种请求,如果都不是,就返回错误。然后解析请求的url,对应到服务器中tinyhttpd中htdocs目录下的文件,检查文件状态,如果文件不存在,那么返回错误。如果文件存在,是GET方法时,tinyhttpd直接返回此文件,通常是html。如果是POST,那么会执行对应的.cgi文件。
     
      
    函数:serve_file(int client, const char *filename)
    功能:向客户端client发送文件filename
    步骤:
    1. 从client读入头部并丢弃。
    2. 以只读方式打开文件filename
    3. 若出错,则发送响应:文件未找到;结束。■
    4. 发送文件:调用cat()
    5. 结束。■
     
     
    函数:execute_cgi() 略。
        等用到CGI时再说。
     
    学到的技巧:
    • 预读socket而不取走数据:recv(sock, &c, 1, MSG_PEEK);
    • fgets/fputs()只能用于读写文本文件。要读写二进制文件,请使用fread/fwrite()。
     
  • 相关阅读:
    learnyou 相关网站
    hdu 3038 How Many Answers Are Wrong
    hdu 3047 Zjnu Stadium 并查集高级应用
    poj 1703 Find them, Catch them
    poj 1182 食物链 (带关系的并查集)
    hdu 1233 还是畅通工程
    hdu 1325 Is It A Tree?
    hdu 1856 More is better
    hdu 1272 小希的迷宫
    POJ – 2524 Ubiquitous Religions
  • 原文地址:https://www.cnblogs.com/xxfcz/p/6165964.html
Copyright © 2020-2023  润新知