#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <sys/wait.h>

#include <stdlib.h>



#define    CGI_NAME "get_post.ums"

#define    REQUEST_METHOD "REQUEST_METHOD=POST"

#define REQUEST_PARAMETER "myname=huangzhihui"



int main(int argc, char *argv[])

{

    int fd[2];

    if (pipe(fd) < 0)

    {

        printf("create pipe fail.\n");

    }



    pid_t pid;

    if ((pid = fork()) < 0)

    {

        printf("fork fail.\n");

    }

    else if (pid > 0)

    {

        /* parent */                

        //模拟向 CGI 传送数据

        ssize_t length = strlen(REQUEST_PARAMETER);

        if (write(fd[1], REQUEST_PARAMETER, length) != length)

        {

            printf("write error to pipe\n");

        }

        close(fd[1]);

        

        //等待CGI子进程全然把数据读取后写入,

        //实际情况应该是使用select 或者 epoll 监听

        usleep(1000);



        //模拟接收 CGI 应答的数据        

        char buff[256] = { 0 };

        length = read(fd[0], buff, sizeof(buff));

        if (length <= 0)

        {

            printf("read error from pipe\n");

        }

        else

        {

            printf("pid %d read data=%u,%s\n",getpid(),length, buff);

        }

        close(fd[0]);



        if (waitpid(pid, NULL, 0) < 0)

        {

            printf("waitpid error\n");

        }

        exit(0);

    }

    else

    {

        /* child */

       //重定向管道的输入端到标准输入

        if (fd[0] != STDIN_FILENO)

        {

            if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)

            {

                printf("dup2 error to stdin");

            }

            close(fd[0]);

        }



        //重定向管道的输出端到标准输出

        if (fd[1] != STDOUT_FILENO)

        {

            if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)

            {

                printf("dup2 error to stdout");

            }

            close(fd[1]);

        }



        //覆盖进程空间,设置CGI环境变量

        char content_length[128] = { 0 };

        sprintf(content_length, "CONTENT_LENGTH=%u", strlen(REQUEST_PARAMETER));

        char *exec_argv[3] = { REQUEST_METHOD, content_length };

        if (execve(CGI_NAME,argv,exec_argv) < 0)

        {

            printf("execl error for %s", CGI_NAME);

        }

        exit(0);

    }

    exit(0);

}

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHpoeHh4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

CGI原理解析之二------WEB服务和CGI交互数据的更多相关文章

  1. Web APi之过滤器执行过程原理解析【二】(十一)

    前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...

  2. CGI原理解析系列之中的一个----CGI怎样获取WEBserver数据

    //gcc get_post.c -o get_post.ums; #include <stdio.h> #include <stdlib.h> #include <un ...

  3. Spring源码:IOC原理解析(二)

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 接着上一章节的内容,我们来分析当new一个FileSystemXmlApplicationContext对象的时候,spring到底做了那 ...

  4. SpringBoot启动流程原理解析(二)

    在上一章我们分析了SpingBoot启动流程中实例化SpingApplication的过程. return new SpringApplication(primarySources).run(args ...

  5. RocketMQ架构原理解析(二):消息存储

    一.概述 由前文可知,RocketMQ有几个非常重要的概念: broker 服务端,负责存储.收发消息 producer 客户端1,负责产生消息 consumer 客服端2,负责消费消息 既然是消息队 ...

  6. kprobe原理解析(二)

    上一篇文章和大家简要说明了下kprobe到底应该怎样用,那么现在我们就揭开kprobe神秘的面纱,刨根问底,一睹kprobe的庐山真面目. kprobe的工作过程大致如下: 1)注册kprobe.注册 ...

  7. 骨骼蒙皮动画(Skinned Mesh)的原理解析(二)

    http://blog.csdn.net/jimoshuicao/article/details/9283071 2)蒙皮信息和蒙皮过程 2-1)Skin info的定义 上文曾讨论过,Skinned ...

  8. APPcrawler基础原理解析及使用

    一.背景 一年前,我们一直在用monkey进行Android 的稳定性测试 ,主要目的就是为了测试app 是否会产生Crash,是否会有ANR,页面错误等问题,在monkey测试过程中,实现了脱离Ca ...

  9. 如何测试Web服务.1

    一.什么是web服务  web服务在简单术语中可被定义为通过安装了特定设备或服务器到另一装置或客户端应用程序通过WWW彼此通信后的应用程序(万维网)提供的服务. Web服务通常在计算机网络的应用层上使 ...

随机推荐

  1. php课程 12-40 抽象类的作用是什么

    php课程 12-40 抽象类的作用是什么 一.总结 一句话总结:定标准的 1.继承的关键词有哪两个? extendsparent 2.抽象类的实际意义是什么? 制造符合规范的产品你必须实现了抽象类里 ...

  2. Swagger文档转Word

    Swagger文档转Word 文档   GitHub 地址:https://github.com/JMCuixy/SwaggerToWord/tree/developer 原创作品,转载请注明出处:h ...

  3. 团队作业-Beta冲刺(1)

    这个作业属于哪个课程 https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass2 这个作业要求在哪里 https://edu.cnblo ...

  4. C语言的多行宏定义

    一.多行宏定义的使用 最近在跟STM32L011K4T6低功耗的源代码,发现使用了多行的宏定义来封装函数,记得之前把\给删除掉,编译程序就一直报错. \是续行操作符,也就是宏定义一行写不完,需要多行写 ...

  5. WPF 入门《布局面板》

    常见的几个布局面板 1.StackPanel面板 StackPanel面板能够简单根据单行或者单列进行元素排列, StackPanel 默认的布局方向为垂直方向(Vertical), 由Orienta ...

  6. 洛谷 P1760 通天之汉诺塔

    P1760 通天之汉诺塔 题目背景 直达通天路·小A历险记第四篇 题目描述 在你的帮助下,小A成功收集到了宝贵的数据,他终于来到了传说中连接通天路的通天山.但是这距离通天路仍然有一段距离,但是小A突然 ...

  7. 96.udp通信

    运行截图 客户端 创建客户端套接字,用于创建UDP通信 SOCKET socket_client; 创建UDP通信 socket_client = socket(AF_INET, SOCK_DGRAM ...

  8. axios封装http请求

    import axios from 'axios' const HTTP_TIMEOUT = 15000; export function httpPost(url, params = {},head ...

  9. 使用ajax发送图片等文件

    1.使用H5的FormData()对象,append()添加文件 2.processData: false, // 告诉jQuery不要去处理发送的数据    contentType: false, ...

  10. JS中的闭包问题总结

    严格意义上的闭包,严格闭包通过栈内存不销毁,保护内部变量,而且下一级作用域可以访问内部变量 更严格意义上的闭包,函数可以在父函数外面调用父函数作用域的值 在函数执行的时候,函数体中有返回值,函数执行的 ...