[项目][WebServer][CGI机制 设计]详细讲解

目录

  • 1.何为CGI机制?
  • 2.理解CGI机制
  • 3.CGI接口设计
    • 1.ProcessNonCgi
    • 2.ProcessCgi


1.何为CGI机制?

  • CGI(Common Gateway Interface)是外部应用程序(CGI程序)与WEB服务器之间的接口标准,是在CGI程序和WEB服务器之间传递信息的过程
    请添加图片描述

2.理解CGI机制

  • 真正理解CGI并不简单,先从现象入手
    • 浏览器除了从服务器获得资源(网页、图片、文字等),有时候还能上传一些东西(提交表单、注册用户之类)
    • 目前HttpServer只能进行获得资源,并不能进行资源上传,所以目前HttpServer并不具有交互式功能
    • 为了让网站能够实现交互式,需要使用CGI功能完成
  • 理论上,可以使用任何语言来编写CGI程序
    • 注意:http提供CGI机制,和CGI程序是两码事
      • 如:学校(http)提供教学平台(CGI机制),学生(CGI程序)来学习
  • 实现上理解,首先要理解GET方法和POST方法的区别
    • GET方法从浏览器传参给http服务器时,是将参数跟套URI后面的
      • 如:www.baidu.com/test_cgi?x=100&y=200
      • GET方法,如果没有传参,http按照一般的方式进行,返回资源即可
        • 静态网页、各种资源
      • GET方法,如果有参数传入,http就需要按照CGI方式处理参数,并将执行结果(期望资源)返回给浏览器
    • POST方法从浏览器传参给http服务器时,是将参数放到请求正文的
      • POST方法,一般都需要使用CGI方式来进行处理
  • 什么时候,需要使用CGI来进行数据处理呢?
    • 只要用户有数据上传上来
  • 如何看待CGI程序呢?
    • 子CGI程序的标准输入时浏览器
    • 子CGI程序的标准输出时浏览器
    • 通信细节由http完成
  • 浏览器和Server进行数据交互的本质,就是进程间通信,也是socket通信的本质
    请添加图片描述

3.CGI接口设计

1.ProcessNonCgi

  • 该接口处理静态网页的请求,只需要将静态网页打开即可
int ProcessNonCgi()
{_response.fd = open(_request.path.c_str(), O_RDONLY);if(_response.fd >= 0){return OK;}return NOT_FOUND;
}

2.ProcessCgi

  • 父子进程间如何传递数据?
    • POST参数、子进程处理结果用匿名管道通信
    • 请求方法、GET参数用环境变量通信
      • 环境变量是具有全局属性的,可以被子进程继承下去,不受exec*程序替换的影响
  • 给子进程传递环境变量时,亲测用setenv()putenv()靠谱些
    • putenv()不会复制传递的字符串大小,而setenv()会的
  • 注意:程序替换,只替换代码和数据,并不替换内核进程相关的数据结构
    • 如文件描述符表
    • 在程序替换之后,数据没有了,但是曾经打开的文件PIPE还在
  • 进程替换之后,子进程如何得知,对应的读写文件描述符时多少呢?
    • 虽然替换后子进程不知道对应的读写fd,但是一定知道0 && 1
    • 此时不需要知道读写fd了,只需要读0写1即可
    • 在执行exec*前,dup2重定向
int ProcessCgi()
{int code = 0; // 退出码std::string &bin = _request.path;// 父子间通信用匿名管道 // TODO 待整理int input[2]; // 父进程读int output[2]; // 父进程写if(pipe(input) < 0){LOG(ERROR, "Pipe Input Error");code = SERVER_ERROR;return code;}if(pipe(output) < 0){LOG(ERROR, "Pipe Output Error");code = SERVER_ERROR;return code;}pid_t id = fork();if(id == 0) // Child{close(output[1]);close(input[0]);// 子进程如何知道方法是什么?setenv("METHOD", _request.method.c_str(), 1);// GET带参通过环境变量导入子进程if(_request.method == "GET"){setenv("ARG", _request.arg.c_str(), 1);LOG(INFO, "GET Method, Add ARG");}else if (_request.method == "POST"){setenv("CLENGTH", std::to_string(_request.content_length).c_str(), 1);LOG(INFO, "POST Method, Add Content_Length");}else{// Do Nothing}// 进程替换之后,子进程如何得知,对应的读写文件描述符是多少呢?// 虽然替换后子进程不知道对应读写fd,但是一定知道0 && 1// 此时不需要知道读写fd了,只需要读0写1即可// 在exec*执行前,dup2重定向dup2(input[1], 1);dup2(output[0], 0);execl(bin.c_str(), bin.c_str(), nullptr);exit(5);}else if(id < 0){LOG(ERROR, "Fork Error");code = SERVER_ERROR;return code;}else // Parent{close(output[0]);close(input[1]);if(_request.method == "POST"){// 不能确保一次性就能写完,所以const char *start = _request.request_body.c_str();int size = 0, total = 0;while (total < _request.request_body.size() &&(size = write(output[1], start + total, _request.request_body.size() - total) > 0)){total += size;}}// 读取CGI子进程的处理结果char ch = 'K';while(read(input[0], &ch, 1) > 0){// CGI执行完之后的结果,并不可以直接返回给浏览器,因为这部分内容只是响应正文_response.response_body += ch;}int status = 0;pid_t ret = waitpid(id, &status, 0);if(ret == id){if(WIFEXITED(status)){if(WEXITSTATUS(status) == 0){code = OK;}else{code = BAD_REQUEST;}}else{code = SERVER_ERROR;}}close(output[1]);close(input[0]);}return OK;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1535207.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

[XILINX] 正点原子ZYNQ7015开发板!ZYNQ 7000系列、双核ARM、PCIe2.0、SFPX2,性能强悍,资料丰富!

正点原子ZYNQ7015开发板&#xff01;ZYNQ 7000系列、双核ARM、PCIe2.0、SFPX2&#xff0c;性能强悍&#xff0c;资料丰富&#xff01; 正点原子Z15 ZYNQ开发板&#xff0c;搭载Xilinx Zynq7000系列芯片&#xff0c;核心板主控芯片的型号是XC7Z015CLG485-2。开发板由核心板&…

JAVA开源项目 在线视频教育平台 计算机毕业设计

本文项目编号 T 027 &#xff0c;文末自助获取源码 \color{red}{T027&#xff0c;文末自助获取源码} T027&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 新…

【数据结构与算法 | 灵神题单 | 合并链表篇】力扣2, 21, 445, 2816

1. 力扣2&#xff1a;两数相加 1.1 题目&#xff1a; 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可…

o1模型:引领AI技术在STEM领域的突破与应用

o1模型是OpenAI最新推出的大型语言模型&#xff0c;它在多个领域展现出了卓越的能力&#xff0c;被认为是AI技术发展的一个重要里程碑。以下是对o1模型的详细介绍和分析&#xff1a; o1模型的简介和性能评估 o1模型在物理、化学、生物学等领域的基准任务上达到了博士生水平&…

Android Studio:驱动高效开发的全方位智能平台

目录 Android Studio 1. 智能的代码编辑与自动补全 2. 快捷键与代码模板 3. 强大的调试工具 4. 实时分析与性能优化 5. 集成的 Gradle 构建系统 6. 持续集成与自动化 7. 版本控制与团队协作 8. 丰富的插件生态与定制化 9. 快速布局与 UI 设计工具 9. 即时运行&#…

数字IC设计\FPGA 职位经典笔试面试--整理

注&#xff1a; 资料都是基于网上一些博客分享和自己学习整理而成的 1&#xff1a;什么是同步逻辑和异步逻辑&#xff1f; 同步逻辑是时钟之间有固定的因果关系。异步逻辑是各时钟之间没有固定的因果关系。 同步时序 逻辑电路的特点&#xff1a;各触发器的时钟端全部连接在一…

MySQL权限管理(DCL)总结

黑马程序员老师讲的非常好 第一个用户管理偏向于开发人员 第二个权限控制偏向于管理人员 但是怎么说呢&#xff0c;你毕竟学mysql了&#xff0c;都得学一学吧。只有精通&#xff0c;实力到位&#xff0c;才能被别人所认可&#xff01;

【打印管理】水印设置支持表单内容

09/11 主要更新模块概览 水印设置 拖动排序 恢复默认 其他更新 01 表单管理 1.1 【打印管理】-水印设置新增支持表单内容 说明&#xff1a; 在打印管理的水印设置中&#xff0c;原本仅支持企业名称作为水…

ROS笔记3.路径规划1

在 Rviz 中可视化路径规划move_base 节点的基本概念什么是Global Planner&#xff1f;什么是Global Costmap&#xff1f; 在 Rviz 中可视化路径规划 对于本章&#xff0c;您基本上需要使用 RViz 的 3 个元素&#xff1a; Map Display (Costmaps)Path Displays (Plans)2D 工具 …

加速开发体验:为 Android Studio 设置国内镜像源

Android Studio 是由 JetBrains 开发的一个官方 IDE&#xff0c;用于 Android 应用开发。由于网络原因&#xff0c;直接从 Google 的服务器下载可能会比较慢或者不稳定。幸运的是&#xff0c;我们可以通过配置国内镜像源来加速下载和更新。 文章目录 &#x1f4af; 修改 Gradle…

Go协程及并发锁应用指南

概念 协程&#xff08;Goroutine&#xff09;是Go语言独有的并发体&#xff0c;是一种轻量级的线程&#xff0c;也被称为用户态线程。相对于传统的多线程编程&#xff0c;协程的优点在于更加轻量级&#xff0c;占用系统资源更少&#xff0c;切换上下文的速度更快&#xff0c;不…

如何快速清理Docker中的停止容器?

如何快速清理Docker中的停止容器? 方法一:使用`docker container prune`方法二:结合`docker ps`和`docker rm`注意(这些命令慎用,确定容器不需要之后再执行)💖The Begin💖点点关注,收藏不迷路💖 Docker容器在停止后可能会占用不必要的磁盘空间。如何清理这些停止的…

linux 双网卡服务器突然断电后网卡单通故障解决

某台linux 双网卡服务器突然断电后网卡单通故障解决 故障现象&#xff1a;断电后重启服务器&#xff0c;主用网卡IP只能同网段访问&#xff0c;其他网段无法访问&#xff0c;备用网卡则正常&#xff1b; 解决方案&#xff1a;route -n查询路由信息&#xff0c;发现主网卡路由…

el-table的树形结构结合多选框使用,实现单选父子联动,全选,反选功能

<template><div><el-table:data"tableData":row-key"rowKey":default-expand-all"defaultExpandAll":tree-props"treeProps"><!-- 开启树形多选 --><el-table-column v-if"showSelection" width…

【视频教程】基于python深度学习遥感影像地物分类与目标识别、分割实践技术应用

我国高分辨率对地观测系统重大专项已全面启动&#xff0c;高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成&#xff0c;将成为保障国家安全的基础性和战略性资源。未来10年全球每天获取的观测数据将超过10PB&#xff0c;遥感大数据时…

【前端】main.js中app.vue中 render函数的作用及使用背景

vue.js中的main.js中的作用是将app组件挂载到页面中&#xff0c;其中app组件是汇总所有组件元素的组件。main.js的创建vue实例。 #认为的版本 import APP from ./App.vue;new Vue({el:#root,template:<App></App>,components:{App}, })#实际的版本 /* 整个项目的入…

el-table表格的展开行,初始化的时候展开哪一行+设置点击行可展开功能

效果&#xff1a; 表格展开行官网使用&#xff1a; 通过设置 type"expand" 和 Scoped slot 可以开启展开行功能&#xff0c;el-table-column 的模板会被渲染成为展开行的内容&#xff0c;展开行可访问的属性与使用自定义列模板时的 Scoped slot 相同。 但是这种方法…

Linux环境基础开发工具---vim

1.快速的介绍一下vim vim是一款多模式的编辑器&#xff0c;里面有很多子命令&#xff0c;来实现代码编写操作。 2.vim的模式 vim一共有三种模式&#xff1a;底行模式&#xff0c;命令模式&#xff0c;插入模式。 2.1vim模式之间的切换 2.2 谈论常见的模式---命令模式&#xf…

Linux 35.5 + JetPack v5.1.3@CUDA安装和版本切换

Linux 35.5 JetPack v5.1.3CUDA安装和版本切换 1. 源由2. 现象3. 分析3.1 看本质3.2 善动脑3.3 笔记回忆3.4 底层思考3.5 多版本 4. 版本切换5. 总结 1. 源由 最近遇到一些CUDA编程&#xff0c;以及编译链接过程出现一些版本不匹配的问题。 首先&#xff0c;申明下&#xff…

No module named MYSQLdb 问题解决

问题&#xff1a; 导入写好的数据库时报错 解决&#xff1a;pip install mysql-python &#xff08;又报错&#xff09; 找了网上的方法&#xff1a; 执行 pip install PyMySQL&#xff0c;将数据库连接改为 mysqlpymysql://username:passwordserver/db&#xff0c;接下来的操…