从零开始一个http服务器-模拟cgi(五)

代码地址 : https://github.com/flamedancer/cserver

git checkout step5

运行:

make clean && make && ./myserver.out

测试

浏览器打开 http://127.0.0.1:9734/action/show_date

模拟cgi:用外部程序来优化 动态 response

  • cgi解释
  • 调用外部程序

cgi解释

上一节中,我们确实是实现了动态的response:我们不需要修改我们的代码,也不需要中断server,只需要修改我们的html页面文件就可以实时的更改返回内容。

但是当需要返回更加灵活的内容,比如当前时间的时候,我们不可能每隔一秒钟就去改下页面文件。这时候就可以借助外部的程序,比如shell,来为我们生产返回内容。这个外部程序,就类似于常说的cgi程序。所谓cgi,维基百科是这么解释:通用网关接口Common Gateway Interface/CGI)是一种重要的互联网技术,可以让一个客户端,从网页浏览器向执行在网络服务器上的程序请求数据。CGI描述了服务器和请求处理程序之间传输数据的一种标准。

这是说CGI是一种标准,只要服务器 和 外部的程序 都实现了这个标准,就可以相互通信。

我们这比较粗鲁一点,我们不管正规的CGI标准是什么,我们定义一个我们自己简单粗暴的标准,这个标准只有两条:

  1. 外部的程序 可以产生 标准输出
  2. 服务器可以获得外部的程序产生的标准输出

这样的话我们就可以把外部的程序的标准输出直接作为response的body。

调用外部程序

执行外部程序的核心函数为popen ,它会开启一个新进程执行传入的外部命令,返回一个管道文件流,读取这个管道文件流就可以读取到外部命令的输出。管道文件流需要用pclose关闭,而不是fclose。

void doCgi(char * filePath, struct http_response * response) {
char fileName[100];
char cmd[100];
sprintf(fileName, "cgi/%s", filePath + strlen(action_url + 1));
sprintf(cmd, "%s 2>&1", fileName); FILE *fstream = NULL;
if (access(fileName, F_OK) == -1 || NULL == (fstream = popen(cmd, "r"))) {
// file doesn't exist or FILE cannot be exec
setResponseMsg(response, errorMsg);
return;
} response->body = (char *)malloc((5000));
int len = 0;
char *buff = response->body;
do {
buff += len;
len = fread(buff, 1024, 1, fstream);
// printf("%d\n", len); } while (len);
pclose(fstream);
response->body_size = strlen(response->body);
struct Item *item2 = newItem(
"Content-Type",
"text/html; charset=utf-8");
mapPush(response->headers, item2); return;
}

建一个目录名为cgi,把我们写的外部程序放到这个目录,例如我们写个 cgi/show_date 程序:

#! /bin/bash
echo $(date)

make clean && make && ./myserver.out 打开 http://127.0.0.1:9734/action/show_date 可以看到实时的时间

从零开始一个http服务器(五)-模拟cgi的更多相关文章

  1. 从零开始一个http服务器(三)-返回response 构造

    从零开始一个http服务器(三) 代码地址 : https://github.com/flamedancer/cserver git checkout step3 运行: gcc request.h ...

  2. 从零开始一个http服务器(六)-多路复用和压力测试

    从零开始一个http服务器(六)-多路复用和压力测试 代码地址 : https://github.com/flamedancer/cserver git checkout step6 运行: make ...

  3. 从零开始一个http服务器(二)-请求request解析

    从零开始一个http服务器 (二) 代码地址 : https://github.com/flamedancer/cserver git checkout step2 解析http request 观察 ...

  4. 从零开始一个http服务器(一)-开始

    从零开始一个http服务器 (一) 代码地址 : https://github.com/flamedancer/cserver git checkout step1 一个简单的socket serve ...

  5. 从零开始一个http服务器(四)-动态返回

    从零开始一个http服务器(四) 代码地址 : https://github.com/flamedancer/cserver git checkout step4 运行: make clean &am ...

  6. 在阿里云服务器(ECS)上从零开始搭建nginx服务器

    本文介绍了如何在阿里云服务器上从零开始搭建nginx服务器.阿里云服务器(ECS)相信大家都不陌生,感兴趣的同学可以到http://www.aliyun.com/product/ecs去购买,或到体验 ...

  7. 用Backbone.js创建一个联系人管理系统(五)

    原文: Build a Contacts Manager Using Backbone.js: Part 5 这是这系列教程最后一部分了. 之前所有的增删改都在前端完成. 这部分我们要把Contact ...

  8. 用java写一个web服务器

    一.超文本传输协议 Web服务器和浏览器通过HTTP协议在Internet上发送和接收消息.HTTP协议是一种请求-应答式的协议——客户端发送一个请求,服务器返回该请求的应答.HTTP协议使用可靠的T ...

  9. 用C写一个web服务器(二) I/O多路复用之epoll

    .container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...

随机推荐

  1. Python实例---三级菜单的实现[high]

    # version: python3.2.5 # author: 'FTL1012' # time: 2017/12/7 09:16 menu = { '陕西': { '西安': { '未名区': [ ...

  2. 在oracle电子商务套件中输出信息

    一.用自定义用户HAND_SL登陆http://zd01.haasgz.hand-china.com:30000/ 添加可执行并发程序 执行文件名填写自己的包名称.入口函数/过程名 二.将可执行程序添 ...

  3. 未能从程序集 C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Data.Entity.Build.Tasks.dll 加载任务“EntityClean”

    问题: 未能从程序集 C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Data.Entity.Build.Tasks.dll 加载任务“Entity ...

  4. css3鼠标经过出现转圈菜单(仿)

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  5. python with原型

    @Python 的 with 语句详解   这篇文章主要介绍了Python 的 with 语句,本文详细讲解了with语句.with语句的历史.with语句的使用例子等,需要的朋友可以参考下   一. ...

  6. 2241. [SDOI2011]打地鼠【暴力+剪枝】

    Description 打地鼠是这样的一个游戏:地面上有一些地鼠洞,地鼠们会不时从洞里探出头来很短时间后又缩回洞中.玩家的目标是在地鼠伸出头时,用锤子砸其头部,砸到的地鼠越多分数也就越高. 游戏中的锤 ...

  7. 【LeetCode每天一题】Remove Duplicates from Sorted Array II(移除有序数组中重复的两次以上的数字)

    Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twic ...

  8. Redmine使用学习

    注:陈刚在公司架设了 Redmine xx公司产品档案管理系统,并且与tortoisegit集成了在一起:真心不错!比如git:192.168.10.46,而redmine:192.168.10.46 ...

  9. 将硬件规定的通信协议用Lua实现(涉及到很多Lua通信的数据转换)

    1:这次处理的是大唐的gps通信协议,先简单介绍一下他规定的通信规则: 信息结构: 传输说明: 信息结构中的各个字节书写时都是以十六进制标识,两位数组成.传输时,SOI和EOI(SOI=7EH,EOI ...

  10. java SSM 框架 多数据源 代码生成器 websocket即时通讯 shiro redis 后台框架源码

    A 调用摄像头拍照,自定义裁剪编辑头像 [新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统]B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,开发利器)+快速构建表单;  技 ...