简单http学习:3 accept_request 函数

重头

void accept_request(int client)
{
  char buf[1024];
  int numchars;
  char method[255];
  char url[255];
  char path[512];
  size_t i, j;
  struct stat st;
  /*
  int stat(
  const char *filename    //文件或者文件夹的路径
  , struct stat *buf      //获取的信息保存在内存中
); 也就是通过提供文件描述符获取文件属性 
stat结构体的元素
struct stat {
        mode_t     st_mode;       //文件对应的模式,文件,目录等
        ino_t      st_ino;        //inode节点号
        dev_t      st_dev;        //设备号码
        dev_t      st_rdev;       //特殊设备号码
        nlink_t    st_nlink;      //文件的连接数
        uid_t      st_uid;        //文件所有者
        gid_t      st_gid;        //文件所有者对应的组
        off_t      st_size;       //普通文件,对应的文件字节数
        time_t     st_atime;      //文件最后被访问的时间
        time_t     st_mtime;      //文件内容最后被修改的时间
        time_t     st_ctime;      //文件状态改变时间
        blksize_t  st_blksize;    //文件内容对应的块大小
        blkcnt_t   st_blocks;     //伟建内容对应的块数量
      };   
  */
  int cgi = 0; /* becomes true if server decides this is a CGI
                    * program */
  char *query_string = NULL;

  numchars = get_line(client, buf, sizeof(buf));
  //读取一行http请求到buf中
  i = 0;
  j = 0;
  //复制buf到method中,但是不能超过method大小255个
  while (!ISspace(buf[j]) && (i < sizeof(method) - 1))
  {
    method[i] = buf[j];
    i++;
    j++;
  }
  method[i] = '\0';//给method增加一个结尾

  //strcasecmp函数忽略大小写的比较字符串函数。
  //若参数s1和s2字符串相等则返回0。s1大于s2则返回大于0 的值,s1 小于s2 则返回小于0的值
  //此函数只在Linux中提供,相当于windows平台的 stricmp。
  //如果既不是get也不是post,服务器无法处理
  if (strcasecmp(method, "GET") && strcasecmp(method, "POST"))
  {
    unimplemented(client);
    return;
  }


  //如果是post,激活cgi
  if (strcasecmp(method, "POST") == 0)
    cgi = 1;
  
  //不管get还是post,都要进行读取url地址
  i = 0;//处理空字符
  while (ISspace(buf[j]) && (j < sizeof(buf)))
    j++;
  while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf)))
  {
    url[i] = buf[j];
    i++;
    j++;
  }
  url[i] = '\0';

  //如果是get可能需要把url划分为两段
  //get请求可能带有?表示查询参数
  if (strcasecmp(method, "GET") == 0)
  {
    query_string = url;
    while ((*query_string != '?') && (*query_string != '\0'))
      query_string++;
    if (*query_string == '?')
    {//如果有?说明需要激活cgi
      cgi = 1;//需要执行cgi,解析参数,设置标志位为1
      *query_string = '\0';//这里变成url结尾
      query_string++;//query_string作为剩下的起点
    }
  }

  sprintf(path, "htdocs%s", url);//把url添加到htdocs后赋给path
  if (path[strlen(path) - 1] == '/')//如果是以/结尾,需要把index.html添加到后面
    //以/结尾,说明path只是一个目录,此时需要设置为首页index.html
    strcat(path, "index.html");//strcat连接两个字符串
  if (stat(path, &st) == -1)//执行成功则返回0,失败返回-1
  {//如果不存在,那么读取剩下的请求行内容丢弃
    while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */
      numchars = get_line(client, buf, sizeof(buf));
    not_found(client);//调用错误代码404
  }
  else
  {
    /*掩码
      #define _S_IFMT 0xF000
      #define _S_IFDIR 0x4000
      #define _S_IFCHR 0x2000
      #define _S_IFIFO 0x1000
      #define _S_IFREG 0x8000
      #define _S_IREAD 0x0100
      #define _S_IWRITE 0x0080
      #define _S_IEXEC 0x0040
    */
    if ((st.st_mode & S_IFMT) == S_IFDIR)//mode_t     st_mode;表示文件对应的模式,文件,目录等,做与运算能得到结果
      strcat(path, "/index.html");//如果是目录,显示index.html这里和前面是否重复?
    if ((st.st_mode & S_IXUSR) ||
        (st.st_mode & S_IXGRP) ||
        (st.st_mode & S_IXOTH))//IXUSR X可执行,R读,W写,USR用户,GRP用户组,OTH其他用户
      cgi = 1;
    

    if (!cgi)//如果不是cgi,直接返回
      serve_file(client, path);
    else
      execute_cgi(client, path, method, query_string);//是的话,执行cgi
  }

  close(client);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值