返回

执行流程

见解分享

## tinyhttpd 源码分析:2. 执行流程及主要函数浅析

tinyhttpd 的执行流程如下图所示:

[Image of tinyhttpd execution flow]
  1. main() 函数:

    • 首先调用 startup() 函数开启一个 TCP 服务器端口。
    • 接收到请求后,main() 函数会创建一个线程执行 accept_request() 函数。
  2. accept_request() 函数:

    • 从监听套接字中接受一个客户端连接。
    • 为该连接创建一个新的线程,并调用 service() 函数。
  3. service() 函数:

    • 解析 HTTP 请求。
    • 根据请求类型和路径调用适当的处理函数。
    • 准备并发送响应。

tinyhttpd 使用的主要函数包括:

  1. startup() 函数:

    • 打开监听套接字并绑定到指定的端口。
    • 初始化线程池。
    • 初始化文件系统。
  2. accept_request() 函数:

    • 从监听套接字中接受一个客户端连接。
    • 为该连接创建一个新的线程,并调用 service() 函数。
  3. service() 函数:

    • 解析 HTTP 请求。
    • 根据请求类型和路径调用适当的处理函数。
    • 准备并发送响应。
  4. handle_file_request() 函数:

    • 处理对静态文件的请求。
    • 读取文件并将其发送给客户端。
  5. handle_cgi_request() 函数:

    • 处理对 CGI 脚本的请求。
    • 执行 CGI 脚本并将输出发送给客户端。

以下是 startup() 函数的示例代码:

void startup(void)
{
    struct sockaddr_in sa;

    /* Open a listening socket */
    s = socket(AF_INET, SOCK_STREAM, 0);
    if (s < 0) {
        perror("socket");
        exit(1);
    }

    /* Bind the socket to the port */
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(PORT);
    sa.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
        perror("bind");
        exit(1);
    }

    /* Start listening */
    if (listen(s, 5) < 0) {
        perror("listen");
        exit(1);
    }

    /* Initialize the thread pool */
    thread_pool_init();

    /* Initialize the file system */
    fs_init();
}