【网络】详解HTTP协议的CGI机制和CGI进程

15 篇文章 1 订阅

目录

引言

CGI机制模型

伪代码示例


个人主页:东洛的克莱斯韦克-CSDN博客

引言

CGI机制是HTTP协议提供的偏底层的一套机制,也是非常重要的机制——它让大量的业务进程和HTPP协议解耦。而CGI进程是业务层的,用来处理各种数据,比如把用户提交上来的数据插入数据库,再比如做某种运算。

CGI机制和CGI进程在概念上是完全不一样的,他们的关系就行老婆和老婆饼一样。

客户端通过HTTP协议向服务器提交数据的方式主要有两种:

1.GET方法请求,GET方法没有请求正文,一般用来拉取服务器的数据,但也可以通过URL的参数提交数据(URL中 ?分隔符后面的就是要提交的数据)

2.POST方法请求,通过请求正文向服务器提交数据

不同的方法的请求,提交的数据量不一样,HTTP底层的CGI机制在处理上也会不一样。

CGI机制模型

简单来说处理HTTP协议请求和响应的服务是父进程,当客户端提交数据给服务器时,HTTP服务会让子进程进行CGI程序替换(让子进程执行exec系列的系统调用),此时子进程就是CGI进程。

【linux】进程间通信(IPC)——匿名管道,命名管道与System V内核方案的共享内存,以及消息队列和信号量的原理概述_linux ipc-CSDN博客父子进程可以用系统提供的进程间通信的方案完成数据的传输。

可以参考小编如下方案

【Linux系统编程】子进程被程序替换后,如何保持父子进程的通信-CSDN博客

伪代码示例

#define ENV "url_parameter"      // 环境变量的k值 ,GET方法的请求的参数通过环境变量传给子进程
#define ENV_M "request_method"   // 环境变量,请求的方法
#define ENV_L "request_len"      // 环境变量,正文的长度
#define ERR_H "wwwroot/err.html" // 返回错误页面的路径
 
void cgi_dispose_request_y() // 用CGI机制处理数据
  {
    //  LOG(INFO, "进入CGI机制的函数了...");
    // 建立信道,相对于父进程来说
    int r_channel[2] = {-1, -1}; // 读信道
    int w_channel[2] = {-1, -1}; // 写信道

    if (0 != pipe(r_channel) || 0 != pipe(w_channel)) // 创建匿名管道
    {
   
    }
    // 创建子进程
    pid_t id = fork();

    if (id == 0) // 子进程
    {
  
      close(r_channel[0]);
      close(w_channel[1]);

      if (setenv(ENV_M, _http_q._method.c_str(), 1) == -1) 
      {
      );
      
      }
      if (setenv(ENV_L, (std::to_string(_http_q.body_line)).c_str(), 1) == -1)
      {
       );
       
      }

      // 在程序替换之前,需要把子进程的读信道和写信道分别重定向到标准输入0,标准输出1中
      if (_http_q.if_url_parameter) // url带参说明它是一个GET请求,用环境变量传递数据
      {
        if (setenv(ENV, _http_q._url_parameter.c_str(), 1) == -1)
        {
          
        }
      }
      // LOG(INFO, "环境变量添加完毕");

      dup2(w_channel[0], 0); // 0号文件描述符,从信道里读
      dup2(r_channel[1], 1); // 1号文件描述符,向信道里写
      // 代码和数据均会被替换,但内核数据不会被替换,包括文件描述符
      if (execl(_http_q._url_path.c_str(), _http_q._url_path.c_str(), nullptr) == -1)
      {
       
      }
    }
    else if (-1 == id)
    {
     
    }
    else // 父进程
    {
    
      close(r_channel[1]);
      close(w_channel[0]);

      if (_http_q.if_url_parameter == false) // url不带参,在这里说明该请求是一个POST请求
      {
        int max = _http_q.body_line;
        for (int i = 0; i < max; i++)
        {
          write(w_channel[1], &_http_q.request_body[i], 1); // 把请求正文写入管道
        }
      }

      char ch = 'x';
      while (read(r_channel[0], &ch, 1) == 1) // 死循环读取数据,管道没有数据阻塞,子进程发送数据完毕退出,文件描述符也会关闭,父进程就会读0,然后退出循环
      {
        _http_p.response_body += ch;
      }

      close(r_channel[0]); // 关闭文件描述符,在网络通信中,文件描述符也是一种很重要的资源
      close(w_channel[1]);

      int code; // 子进程的退出状态
      waitpid(id, &code, 0);
      if (WIFEXITED(code)) // 如果子进程是正常退出
      {
        
      }
      else
      {
      
      }
    }
  }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值