mini-httpd源码分析-mini-httpd.c

main函数分析;

一,参数设置:  读取命令行参数

         配置文件参数

      读取参数,设置对应的全局变量。主要参数有:配置文件;资源目录;进程ID文件;日志文件;字符集;主机名及端口号...

二,参数处理:重点分析,主机名及端口号,damon

  1,主机名及端口号

    解析主机名,获取对应IP地址,初始化监听套接字(包括:socket,bind,listen)

    以IPv4为例:

      listen_fd=socket(AF_INET,SOCK_STREAM,0);创建套接字

      套接字选项设置:设置方法有fcntl,setsockopt

      1,fcntl(listen_fd,F_SETFD,FD_CLOEXEC); 设置close-on-exec,exec进程时,关闭此文件描述符

      2,  int i=1;

           setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,(void*)&i,sizeof(i));可重用本地地址

      3,bind(listen_fd,struct sockaddr* -,sizeof(-));绑定套接字和IP:端口

      4,listen(listen_fd,1024);设置监听套接字最大队列长度

  2,若不是调试模式,则应该设置为damon模式,

    switch(fork()){

      case 0: break;  子进程继续执行

      case -1:    出错,退出程序

      default:exit(-1);  父进程退出

    }

  3,信号处理设置:

    SIGTERM: kill发送系统中断进程信号

    SIGINT: 用户终端Ctrl+C中断进程

    SIGHUP:一般用来通知守护进程再次读取配置文件等作用,因为守护进程没有终端,不会收到此信号。此处用于再次读取日志文件

    SIGCHLD:子进程退出时,会发送该信号给父进程,父进程应该捕捉,否则将产生僵尸进程

    SIGPIPE:管道读关闭时写,套接字不再连接时写,都会产生此信号。网络编程中出现的很多

  4,服务器主循环:

    若收到SIGHUP信号,则再次打开日志文件(覆盖),若需要可备份

      select模式,多路复用:阻塞模式

      FD_ZERO(&lfdset);清空描述符集

      FD_SET(listen_fd,&lfdset);条件套接字描述符到描述符集中

      设置select阻塞读,select(listen_fd+1,&lfdset,NULL,NULL,NULL);永远阻塞,直到listen_fd可读;

    若listen_fd可读,调用accept,获得已连接套接字描述符,若出错(EAGAIN,资源暂不可用;EINTR,中断函数调用;ECONNABORT,连接中断。continue,try again),否则异常退出。

    若连接成功,fork(),子进程处理请求,父进程继续循环,监听。

      子进程关闭监听套接字,调用 handle_request 函数处理请求,退出;父进程关闭已连接套接字,继续循环监听。

  5,handle_request函数解析

    超时设置:利用信号SIGALRM,alarm(60);

      [设置TCP_NOPUSH套接字选项]

    读取请求:循环read,把读取的数据存入全局变量request中,每次读取后,重新设置超时alarm(60)

    请求解析: get_request_line()

      解析请求的第一行:分三部分:方法,路径,协议

      解析请求其余部分:name:value...初始化对应的全局变量

    方法字符串分解:方法(GET,HEAD,POST),查询字符串query,?之后

    路径解析:获取文件名file

    超时设置,SIGALRM(写超时设置)

    响应:构造请求响应(报头及实体),写套接字(循环write),发送响应。

原文地址:https://www.cnblogs.com/jokoz/p/4795182.html