fastCGI快速上手

news2025/2/27 20:56:40

fastCGI


OVERVIEW

  • fastCGI
      • 一、CGI
      • 二、fastCGI
      • 三、fastCGI使用
        • 1.fastCGI和spawn-fcgi安装
        • 2.nginx + fastcgi
          • (1)nginx的数据转发
          • (2)spawn-fcgi启动
          • (3)fastCGI进程处理
        • 3.fastCGI总结
      • 四、其他
        • 1.fastCGI环境变量
        • 2.Post提交数据常用方式
          • application/x-www-form-urlencoded
          • application/json
          • text/xml
          • multipart/form-data
        • 3.strtol与strtoul字符串转进制数
          • strtol
          • strtoul

一、CGI

通用网关接口(Common Gateway Interface/CGI)描述了客户端和服务器程序之间传输数据的一种标准,可以让一个客户端从网页浏览器向执行在网络服务器上的程序请求数据。CGI 独立于任何语言的,CGI 程序可以用任何脚本语言或者是完全独立编程语言实现,只要这个语言可以在这个系统上运行。

在这里插入图片描述

在这里插入图片描述

  1. 用户通过浏览器访问服务器, 发送了一个请求, 请求的url如上
  2. 服务器接收数据, 对接收的数据进行解析
  3. nginx对于一些登录数据不知道如何处理, nginx将数据发送给了cgi程序
  4. 服务器端会创建一个cgi进程,CGI进程执行
    • 加载配置, 如果有需求加载配置文件获取数据
    • 连接其他服务器: 比如数据库
    • 逻辑处理得到结果, 将结果发送给服务器
    • 线程结束生命退出
  5. 服务器将cgi处理结果发送给客户端
  6. 弊端:在服务器端CGI进程会被频繁的创建销毁,服务器开销大, 效率低

二、fastCGI

快速通用网关接口FastCommonGatewayInterface是通用网关接口CGI的改进,描述了客户端和服务器程序之间传输数据的一种标准。

FastCGI致力于减少Web服务器与CGI程序之间互动的开销,从而使服务器可以同时处理更多的Web请求。

与为每个请求创建新的进程不同,FastCGI使用持续的进程来处理一连串的请求(线程不会被销毁)。

这些进程由FastCGI进程管理器管理,而不是web服务器。

  • fastCGI与CGI的区别:CGI 就是所谓的短生存期应用程序,FastCGI 就是所谓的长生存期应用程序。FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,不会每次都要花费时间去fork一次

在这里插入图片描述

  1. 用户通过浏览器访问服务器, 发送了一个请求, 请求的url如上

  2. 服务器接收数据, 对接收的数据进行解析

  3. nginx对于一些登录数据不知道如何处理, nginx将数据发送给了fastcgi程序

    • 通过本地套接字
    • 网络通信的方式
  4. fastCGI程序如何启动:不是有web服务器直接启动,通过一个fastCGI进程管理器启动

    • 加载配置(可选)
    • 连接服务器 - 数据库,循环
      • 服务器有请求 -> 处理,将处理结果发送给服务器:本地套接字、网络通信
      • 没有请求 -> 阻塞
  5. 服务器将fastCGI的处理结果发送给客户端

  6. fastcgi启动

三、fastCGI使用

1.fastCGI和spawn-fcgi安装

安装fastCGI

./configure
make
- fcgio.cpp:50:14: error: 'EOF' was not declared in this scope
- 没有包含对应的头文件:
	- stdio.h - c
	- cstdio -> c++
sudo make install

安装spawn-fcgi

./configure
make
sudo make install

2.nginx + fastcgi

nginx不能像apache那样直接执行外部可执行程序,但nginx可以作为代理服务器,将请求转发给后端服务器(主要作用),

其中nginx就可以支持FastCGI作为代理,由nginx接收客户端的请求,然后将请求转发给fastcgi进程进行实际处理。

使用spawn-fcgi作为FastCGI进程的管理器,管理fastcgi进程,spawn-fcgi使用pre-fork 模型,功能主要是打开监听端口,绑定地址,然后fork-and-exec创建我们编写的fastcgi应用程序进程,退出完成工作。

在这里插入图片描述

  1. 客户端访问, 发送请求
  2. nginx web服务器, 无法处理用户提交的数据
  3. spawn-fcgi - 通信过程中的服务器角色
    • 被动接收数据
    • 在spawn-fcgi启动的时候给其绑定IP和端口
  4. fastCGI程序
    • 开发者编写的 -> login.c -> 可执行程序( login )
    • 使用 spawn-fcgi 进程管理器启动 login 程序, 得到一进程
(1)nginx的数据转发

需要修改nginx的配置文件 nginx.conf

通过请求的 url http://localhost/login?user=zhang3&passwd=123456&age=12&sex=man 转换为一个指令:
	- 去掉协议
	- 去掉域名/IP + 端口
	- 如果尾部有文件名 去掉
	- 去掉 ? + 后边的字符串
	- 剩下的就是服务器要处理的指令: /login
location /login
{
    # 转发这个数据, fastCGI进程
    fastcgi_pass 地址信息:端口;
    # fastcgi.conf 和nginx.conf在同一级目录: /usr/local/nginx/conf
    # 这个文件中定义了一些http通信的时候用到环境变量, nginx赋值的
    include fastcgi.conf;
}
地址信息: 
	- localhost
	- 127.0.0.1
	- 192.168.1.100
端口: 找一个空闲的没有被占用的端口即可
(2)spawn-fcgi启动
# 前提条件: fastCGI程序已经编写完毕 -> 可执行文件 login
spawn-fcgi -a IP地址 -p 端口 -f fastcgi可执行程序
 - IP地址: 应该和nginx的 fastcgi_pass 配置项对应
 	- nginx: localhost   ->   IP: 127.0.0.1
	- nginx: 127.0.0.1	 ->   IP: 127.0.0.1
	- nginx: 192.168.1.100   ->    IP: 192.168.1.100
- 端口:
	应该和nginx的 fastcgi_pass 中的端口一致
(3)fastCGI进程处理
// http://localhost/login?user=zhang3&passwd=123456&age=12&sex=man
// 要包含的头文件
#include "fcgi_config.h" // 可选
#include "fcgi_stdio.h" // 必须的, 编译的时候找不到这个头文件, find->path , gcc -I
// 编写代码的流程
int main()
{
    // FCGI_Accept()是一个阻塞函数, nginx给fastcgi程序发送数据的时候解除阻塞
    while (FCGI_Accept() >= 0)
    {
        // 1. 接收数据
        // 1.1 get方式提交数据 - 数据在请求行的第二部分
        // user=zhang3&passwd=123456&age=12&sex=man
        char *text = getenv("QUERY_STRING"); 
        // 1.2 post方式提交数据
        char *contentLength = getenv("CONTENT_LENGTH");
        // 根据长度大小判断是否需要循环
        
        // 2. 按照业务流程进行处理
        
        // 3. 将处理结果发送给nginx(纯文本|json|html|...)
        // 数据回发的时候, 需要告诉nginx处理结果的格式 - 假设是html格式
        printf("Content-type: text/html\r\n");
        printf("<html>处理结果</html>");
    }
}
  • 一个文件描述符在内核中对应两块缓冲区,读缓冲区、写缓冲区

  • 利用dup2函数对标准输入输出进行了重定向,重定向到fd对应的读写缓冲区中

  • 所以对标准输入输出的操作其实就是对fd文件描述符的操作

在这里插入图片描述

3.fastCGI总结

  1. fastCGI是什么?:运行在服务器端的代码, 帮助服务器处理客户端提交的动态请求

  2. fastCGI作用:帮助服务器处理客户端提交的动态请求,

  3. fastCGI如何使用?

    • fastCGI如何获取数据?nginx解析客户端发送的http请求然后转发

      # 分析出客户端请求对应的指令 -- /test
      location /test
      {
          # nginx转发出去给fastcgi程序
          fastcgi_pass 地址:端口;
          include fastcgi.conf;//nginx对http请求解析得到的环境变量
      }
      
    • fastcgi如何接收数据?spawn-fcgi与fastcgi是父子进程关系,

      # 启动, 通过spawn-fcgi启动
      spawn-fcgi -a IP -p port -f ./fcgi
      # 编写fastCGI程序的时候
       - 接收数据: 调用读终端的函数就是接收数据
       - 发送数据: 调用写终端的函数就是发送数据
      
    • fastcgi如何处理数据?

      // 编写登录的fastCgI程序
      int main()
      {
          while(FCGI_Accept() >= 0)
          {
              // 1. 接收登录信息 -> 环境变量中(post|get)
              // post -> 读数据块的长度 CONTENT-LENGTH
              // get -> 从请求行的第二部分读 QUEERY_STRING
              
              // 2. 处理数据
              
              // 3. 回发结果 -> 格式假设是json
              printf("Content-type: application/json");
              printf("{\"status\":\"OK\"}")
          }
      }
      

四、其他

1.fastCGI环境变量

fastCGI环境变量 - fastcgi.conf

环境变量说明
SCRIPT_FILENAME脚本文件请求的路径
QUERY_STRING请求的参数;如?app=123
REQUEST_METHOD请求的动作(GET,POST)
CONTENT_TYPE请求头中的Content-Type字段
CONTENT_LENGTH请求头中的Content-length字段
SCRIPT_NAME脚本名称
REQUEST_URI请求的地址不带参数
DOCUMENT_URI与$uri相同
DOCUMENT_ROOT网站的根目录。在server配置中root指令中指定的值
SERVER_PROTOCOL请求使用的协议,通常是HTTP/1.0或HTTP/1.1
GATEWAY_INTERFACEcgi 版本
SERVER_SOFTWAREnginx 版本号,可修改、隐藏
REMOTE_ADDR客户端IP
REMOTE_PORT客户端端口
SERVER_ADDR服务器IP地址
SERVER_PORT服务器端口
SERVER_NAME服务器名,域名在server配置中指定的server_name

2.Post提交数据常用方式

客户端使用Post提交数据常用方式

  • Http协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。

  • 开发者完全可以自己决定消息主体的格式

  • 数据发送出去,还要服务端解析成功才有意义, 服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。

application/x-www-form-urlencoded
# 请求行
POST http://www.example.com HTTP/1.1
# 请求头
Content-Type: application/x-www-form-urlencoded;charset=utf-8
# 空行
# 请求数据(向服务器提交的数据)
title=test&user=kevin&passwd=32222
application/json
POST / HTTP/1.1
Content-Type: application/json;charset=utf-8
{"title":"test","sub":[1,2,3]}
text/xml
POST / HTTP/1.1
Content-Type: text/xml
<?xml version="1.0" encoding="utf8"?>
<methodcall>
    <methodname color="red">examples.getStateName</methodname>
    <params>
    	<value><i4>41</i4></value>
    </params>
</methodcall>

<font color="red">nihao, shijie</font>
multipart/form-data

multipart/form-data用于传输大文件,

POST / HTTP/1.1
Content-Type: multipart/form-data
# 发送的数据
------WebKitFormBoundaryPpL3BfPQ4cHShsBz \r\n
Content-Disposition: form-data; name="file"; filename="qw.png"
Content-Type: image/png\r\n; md5="xxxxxxxxxx"
\r\n
.............文件内容................
.............文件内容................
------WebKitFormBoundaryPpL3BfPQ4cHShsBz--
Content-Disposition: form-data; name="file"; filename="qw.png"
Content-Type: image/png\r\n; md5="xxxxxxxxxx"
\r\n
.............文件内容................
.............文件内容................
------WebKitFormBoundaryPpL3BfPQ4cHShsBz--

3.strtol与strtoul字符串转进制数

strtol
  • 功能是将一个任意1-36进制数转化为10进制数,返回是long int型。把参数 str 所指向的字符串根据给定的 base 转换为一个长整数(类型为 long int 型),base 必须介于 2 和 36(包含)之间,或者是特殊值 0。

  • strtol() 会扫描参数 str 字符串,跳过前面的空白字符(例如空格,tab缩进等,可以通过 isspace() 函数来检测),直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时(’\0’)结束转换,并将结果返回。

  • 当 base 的值为 0 时,默认采用 10 进制转换,但如果遇到 ‘0x’ / ‘0X’ 前置字符则会使用 16 进制转换,遇到 ‘0’ 前置字符则会使用 8 进制转换。

  • 若endptr 不为NULL,则会将遇到的不符合条件而终止的字符指针由 endptr 传回;若 endptr 为 NULL,则表示该参数无效,或不使用该参数。

  • 返回值:

    返回转换后的长整型数;

    如果不能转换或者 str 为空字符串,那么返回 0(0L);

    如果转换得到的值超出 long int 所能表示的范围,函数将返回 LONG_MAX 或 LONG_MIN,并将 errno 的值设置为 ERANGE

// 将数字类型的字符串 -> 整形数
long int strtol(const char *str, char **endptr, int base);
	- 参数str: 要转换的字符串 - 数字类型的字符串: "123", "0x12", "0776"
	- 参数endptr: 测试时候使用, 一般指定为NULL
	- 参数base: 进制的指定
		- 10 , str = "123456", 如果是"0x12"就会出错
        - 8  , str = "0345"
        - 16,  str = "0x1ff"

char* p = "123abc";
char* pt = NULL;
strtol(p, &pt, 10);
 - 打印pt的值: "abc"
//http://tool.oschina.net/
strtoul
  • 功能是将字符串转换成unsigned long,把参数 str 所指向的字符串根据给定的 base 转换为一个无符号长整数,base 必须介于 2 和 36(包含)之间,或者是特殊值 0。

  • 当 base 的值为 0 时,默认采用 10 进制转换,但如果遇到 ‘0x’ / ‘0X’ 前置字符则会使用 16 进制转换,遇到 ‘0’ 前置字符则会使用 8 进制转换。

  • 若 endptr 不为NULL,则会将遇到的不符合条件而终止的字符指针由 endptr 传回;若 endptr 为 NULL,则表示该参数无效,或不使用该参数。

  • 返回值:

    返回转换后的无符号长整型数;

    如果不能转换或者 str 为空字符串,那么返回 0;

    如果转换得到的值超出unsigned long int 所能表示的范围,函数将返回 ULONG_MAX,并将 errno 的值设置为 ERANGE

#define strtoul simple_strtoul  
#define TOLOWER(x) ((x) | 0x20)   //在是字母的情况下,大写转小写

static unsigned int simple_guess_base(const char *cp) { 
    if (cp[0] == '0') {  
        if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))  
            return 16;  
        else  
            return 8;  
    } else {  
        return 10;  
    }  
}

unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) {  
    unsigned long result = 0;
    if (!base) base = simple_guess_base(cp);
    if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x') cp += 2;
    
    while (isxdigit(*cp)) {  
        unsigned int value;  
        value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;  
        if (value >= base) break;  
        result = result * base + value;  
        cp++;
    }
  
    if (endp) *endp = (char *)cp;  
    return result;  
}  

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

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

相关文章

【图像分割】LabelMe基本使用/标注标签格式转换及可视化

前言 之前一直在做目标检测的相关内容&#xff0c;使用LabelImg标注检测数据轻车熟路。不过最近尝试探索一下图像分割场景&#xff0c;需要用到LabelMe标注用于分割的数据标签&#xff0c;本文进行过程记录。 图像分割数据标签示例 以道路分割为例&#xff0c;下图是deepglo…

基于MVC+SSH的文章发布系统源码数据库毕业论文

目 录 摘要 1 Abstract 2 1 绪论 1.1 课题背景 1.2 研究现状及发展趋势 1.3 课题意义与目的 1.4 研究内容 1.5 论文组织 2 开发工具和技术介绍 2.1 开发工具 2.1.1 Myeclipse简介 2.1.2 MySQL简介 2.1.3 Tomcat简介 2.2 开发技术 2.…

【LInux】MySQL高可用之主从复制

一、Mysql主从架构技术说明 Mysql内建的复制功能是构建大型&#xff0c;高性能应用程序的基础。将Mysql的数据分布到 多个系统上去&#xff0c;这种分布的机制&#xff0c;是通过将Mysql的某一台主机&#xff08;Master&#xff09;的数据复 制到其它主&#xff08;slaves&…

音频模块的介绍

一、术语总结 1.HIFI 级   “HIFI”一词通常指高保真音频&#xff08;High-Fidelity Audio&#xff09;&#xff0c;是指尽可能保持音频信号的原始质量&#xff0c;让听众感受到最真实的音乐表现。因此&#xff0c;“HIFI级”通常指具有高保真音频性能的产品或设备&#xff…

音视频开发十六:SDL基础概念

SDL 纹理渲染 纹理 ​ 在SDL中&#xff0c;纹理是图像的描述信息。用SDL_Texture表示一个纹理对象&#xff08;texture&#xff09;&#xff0c;它是一个用于存储像素数据的结构体类型。 渲染 ​ **互联网解释&#xff1a;**渲染是在电脑绘图中是指用软件从模型生成图像的…

【Linux】线程互斥详解:多线程会有什么问题?什么是互斥锁?C++怎么封装使用互斥锁?

多线程可以提高程序的并发性和运行效率&#xff0c;充分利用计算机的多核资源. 前面的几篇文章已经介绍了, Linux线程的基本概念、基本控制等内容. 我们已经看到了多线程可以提升运行效率等. 但是, 也发现了问题, 多线程可能会导致输出混乱、访问共享资源混乱、竞争等问题. 输…

Vue中 import ...与import{ }、import from ‘@路径‘ 与 import from ‘../路径‘

遇到的问题&#xff1a; 不带{ }以组件方式 引入后&#xff0c;用 组件名. 变量 的方式一直提示变量未定义的问题&#xff0c;改成直接 带{ }引入变量直接使用变量就不提示错误了&#xff0c;&#xff08;不知道是不是我引入的包和他人不一样的原因...&#xff09;&#xff0…

至尊宝工具箱 - 电商运营选品必备工具下载安装详细教程

简介 至尊宝插件是一款电商网络浏览插件&#xff0c;能够帮助店主更好地运营自己的网店&#xff0c;这款插件功能十分全面强大&#xff0c;可以实现搜主图、快速商家商品、优化商品标题等&#xff0c;通过帮助店家增加曝光量来增效销售&#xff0c;感兴趣的朋友快来体验。 下…

使用Superlink控制物联网网关远程调试PLC示例(PLC/HMI调试工具)

目录 1.Superlink工具使用说明 1.1软件安装 1.2账号登录 1.3设备查看 1.4菜单栏使用 2. Superlink网关远程调试网口/串口设备示例 2.1 远程调试西门子网口1200 PLC示例 2.2 远程调试欧姆龙232 PLC实串口通讯示例 3. 常见使用问题及技术支持 3.1 Superlink工具使用问题…

Mybatis核心

文章目录前言一、Configuration二、MappedStatement三、SqlSession四、Executor五、StatementHandler六、ParameterHandler七、ResultSetHandler八、TypeHandler总结前言 SqlSession是MyBatis提供的面向用户的操作数据库API。那么MyBatis底层是如何工作的呢&#xff1f;为了解…

vue.js表情文本输入框组件

文章目录参考链接效果图代码emoji.jsonEmojiText.vue使用参考链接 JS操作文本域获取光标/指定位置插入 vue.js支持表情输入 ttkwsd博客 效果图 代码 不能换行的bug已处理… emoji.json 表情图片放在public的emoji文件夹下面 emoji.json放在src/components/EmojiText文件夹…

Linux 生成pem文件 用于免密登录

1.在远程机器生成.pem文件 生成密钥对&#xff1a; $ ssh-keygen -t rsa -b 2048 -v 直接确认下一步 查看生成的密钥对&#xff1a; $ ls ~/.ssh/ 将私钥重命名至id_rsa.pem&#xff1a; $ mv ~/.ssh/id_rsa ~/.ssh/id_rsa.pem 修改~/.ssh/目录权限&#xff1a; $ chmod …

力扣sql中等篇练习(三)

力扣sql中等篇练习(三) 1 树节点 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # not in匹配上了返回的值是1,casw when里面也是可以使用not in和子查询的 # 注意去重的时候需要筛选掉null值 SELECT id,case when p_id is null then Rootwhen (id …

暄桐好作业之《临王蒙〈具区林屋图〉》

告诉大家一个好消息“暄桐好作业”栏目上新啦~除了与大家分享正在进行的课程好作业&#xff0c;还会向大家展示来自暄桐学长学姐们的优秀国画作品。希望正在上课的暄桐同学们能够从学长学姐的分享以及暄桐教室专业助教的点评中&#xff0c;从中获益并获得力量&#xff0c;继续努…

Java基础(十七):日期时间API

Java基础系列文章 Java基础(一)&#xff1a;语言概述 Java基础(二)&#xff1a;原码、反码、补码及进制之间的运算 Java基础(三)&#xff1a;数据类型与进制 Java基础(四)&#xff1a;逻辑运算符和位运算符 Java基础(五)&#xff1a;流程控制语句 Java基础(六)&#xff1…

chatGPT开发公司

OpenAI是chatGPT的开发公司&#xff0c;成立于2015年&#xff0c;总部位于美国旧金山。OpenAI致力于开发和推广人工智能技术&#xff0c;包括自然语言处理、视觉识别、机器学习等领域&#xff0c;旨在推动人工智能技术对全球社会和经济的影响和发展。 除了chatGPT之外&…

日撸 Java 三百行day31

文章目录day31 整数矩阵及其运算面向对象思想java异常处理java中的getter和setter方法代码day31 整数矩阵及其运算 面向对象思想 结合之前day7和day8面向过程开发&#xff0c;只关注了矩阵加法和矩阵乘法的功能。而day31是面向对象开发&#xff0c;一个矩阵类&#xff0c;在这…

Python实现驾考自动答题,隔壁老王每次都100分....

人生苦短&#xff0c;我用python 不知道大家都考完驾照没&#xff1f; 这个驾照不管大家有没有&#xff0c;我相信大家都是这个&#xff1a; 朋友最近在考驾照&#xff0c;快考科一了… 我微微一笑当场给他整个活~ 用Python整了几十行代码&#xff0c;给朋友实现一下自动答…

前端面试题 - 基础(HTML、HTTP、WEB)

文章目录1、前端 SEO 需要注意哪些2、img 标签上的 title 和 alt 区别3、浏览器输入 url 到显示过程4、浏览器渲染过程5、常见请求方式6、常见的状态码7、网站性能优化8、语义化理解9、浏览器内核理解10、H5的新特性11、离线存储使用&#xff0c;工作原理12、浏览器是如何管理和…

确保实时操作系统(RTOS)设备中的数据安全

导读1月28日大家庆祝了数据保护日&#xff0c;这是一项旨在促进保护数据隐私和安全的国际活动。为了提高人们对数据保护的意识&#xff0c;讨论实时操作系统中数据安全的问题势在必行。目前非常规操作系统已被广泛使用&#xff0c;所以了解这一系统非常重要&#xff0c;尤其是涉…