web服务选择lighttpd,采用fcgi组件技术扩展处理业务层
目录
一、简介fcgi:web和web服务器间数据传输的桥梁... 2
二、源码编译配置ARM Lighttpd Fastcgi C.. 3
【1】交叉编译。源文件都从官网下载。 Fcgi lighttpd zlib. 3
【2】配置服务器server.document-root="/www" fastcgi.server "bin-path" => "/www/fastcgi.fcgi", 4
【3】fastcgi编程程序 将生成的文件拷贝到设备/www目录中... 4
【4】启动服务器... 6
【5】测试... 6
三、fastcgi编程实例... 7
多线程请求例子... 7
四、fcgiapp各个数据结构和函数含义... 9
FCGX_Stream该struct定义了FastCGI流的状态。... 9
FCGX_Request对一个请求的封装。可供访问的属性:... 9
int FCGX_Init() Initialize the FCGX library. 10
int FCGX_InitRequest(FCGX_Request *request, int sock, int flags). 10
int FCGX_Accept_r(FCGX_Request *request) 接受一个新的请求(多线程安全)。... 10
int FCGX_PutChar(int c, FCGX_Stream *stream) 将字符c写入stream。... 10
int FCGX_PutStr(const char *str, int n, FCGX_Stream *stream) 用于二进制输出。... 11
int FCGX_PutS(const char *str, FCGX_Stream *stream) 用于输出字符串。... 11
int FCGX_FPrintF(FCGX_Stream *stream, const char *format, ...) 将格式化字符串format写入stream。 11
int FCGX_GetChar(FCGX_Stream *stream) 从输入读取一个字节。... 11
int FCGX_UnGetChar(int c, FCGX_Stream *stream) 将字符c推回输入流stream。... 11
int FCGX_GetStr(char *str, int n, FCGX_Stream *stream) 从stream中读取n个连续字节到str中。 12
char *FCGX_GetLine(char *str, int n, FCGX_Stream *stream) 从stream中读取n-1个连续字节到str中。 12
int FCGX_HasSeenEOF(FCGX_Stream *stream) 在读取stream时,如果检测到EOF,那么返回EOF,否则返回0。 12
五、Lighttpd 网页服务源码分析说明post数据lighttpd主程序不处理,而是交给动态执行模块fastcgi等来解析。 12
六、参考... 15
lighttpd fastcgi的搭建... 15
fastcgi 分布式... 15
fcgiapp各个数据结构和函数含义... 15
FastCGI编程介绍... 15
在FastCGI应用程序中无法获取HTTP POST的主体... 16
一、简介fcgi:web和web服务器间数据传输的桥梁
FastCGI就像CGI一样,FastCGI也是独立于编程语言的。
是web和web服务器间数据传输的桥梁。
就像CGI一样,FastCGI程序运行在完全独立于核心Web Server之外的进程中,
Fastcgi的缺点:
1、对某些服务器的新版本支持不好,对分布式负载均衡没要求的模块化安装是否是更好的选择。
2、目前的fastcgi和server沟通还不够智能,一个fastcgi进程如果执行时间过长会被当成是死进程杀掉重起,这样在处理长时间任务的时候很麻烦.这样做也使得fastcgi无法允许联机调试。
lighttpd提供了一种外部程序调用的接口,即FastCGI接口。这是一种独立于平台和服务器的接口,它介于Web应用程序和Web服务器之间。
FastCGI工作方式是接受Web服务器的请求,以HTTP Request的方式进行响应,实现了应用程序与Web服务器的分离。它的使用需要在Web服务器中安装支持组件,目前支持Apache、Nginx、IIS、Lighttpd等。
优点有:
- 稳定性,fastcgi是以独立的进程池运行来cgi,单独一个进程死掉,系统可以很轻易的丢弃,然后重新分配新的进程来运行逻辑
- 安全性,fastcgi和宿主的server完全独立,fastcgi怎么down也不会把server搞垮
- 性能, fastcgi把动态逻辑的处理从server中分离出来, 大负荷的IO处理还是留给宿主server, 这样宿主server可以一心一意作IO,对于一个普通的动态网页来说,,逻辑处理可能只有一小部分,大量的图片等静态IO处理完全不需要逻辑程序的参与
- 扩展性,fastcgi是一个中立的技术标准,完全可以支持任何语言写的处理程序(php、java、python、C++)
FastCGI编程包括四部分:初始化编码、接收请求循环、响应内容、响应结束循环。
CGI能够使用C语言编写,以通过共享内存等方式与其他C语言进程通讯。对CGI程序的每个HTTP请求,web服务器都会创建一个新的CGI进程,web服务器通过环境变量传递http请求,CGI程序通过标准输出返回处理结果,然后退出。
fastcgi使用循环响应HTTP请求,服务器负载比cgi小,能与其他程序(如数据库)保持持续链接。fastcgi可以使用tcp或UNIX domain与web服务器通讯,并将HTTP请求转换为环境变量传入,TCP方式中使用标准输出返回处理结果,UNIX domain方式则使用fastcgi封装的函数。cgi-fcgi程序能够将cgi程序作为fastcgi程序运行。
lighttpd支持fastcgi,能够启动fastcgi程序,并进行负载均衡。
二、源码编译配置ARM Lighttpd Fastcgi C
【1】交叉编译。源文件都从官网下载。 Fcgi lighttpd zlib
http://download.lighttpd.net/lighttpd/releases-1.4.x/lighttpd-1.4.33.tar.bz2
http://www.fastcgi.com/dist/fcgi.tar.gz
http://zlib.net/zlib-1.2.8.tar.gz
tar xf zlib-1.2.8.tar.gz
cd zlib-1.2.8
CC=arm-linux-gcc ./configure --prefix=/home/armroot
make
make install
tar xf fcgi.tar.gz
cd fcgi-2.4.1-SNAP-0311112127/
./configure --host=arm-linux --prefix=/home/armroot
make
make install
tar xf lighttpd-1.4.33.tar.bz2
cd lighttpd-1.4.33
./configure --host=arm-linux --prefix=/home/armroot --without-bzip2 --without-pcre
make
make install
拷贝可执行文件(这里是/home/armroot/sbin/lighttpd) 到设备中(我放在了/usr/local/bin/下)。
拷贝lighttpd的mod(这里是/home/armroot/lib/mod*.so)到设备中(我放在了/opt/lighttpd下)
【2】配置服务器server.document-root="/www" fastcgi.server "bin-path" => "/www/fastcgi.fcgi",
/etc/lighttpd.conf
server.document-root="/www"
server.port=80
mimetype.assign=(
".html" => "text/html",
".json" => "text/plain",
".css" => "text/css"
)
server.modules = ("mod_fastcgi", "mod_compress",
)
server.errorlog = "/tmp/lighttpd/error.log"
server.indexfiles = ("index.html")
compress.cache-dir = "/tmp/lighttpd/cache/"
compress.filetype = ("text/plain","text/html","text/css","text/javascript")
fastcgi.debug=0
fastcgi.server = (
".fcgi" =>
(
"main" =>
(
"host" => "127.0.0.1",
"port" => 2048,
"bin-path" => "/www/fastcgi.fcgi",
"max-procs" => 1,
)
)
)
【3】fastcgi编程程序 将生成的文件拷贝到设备/www目录中
test.c
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcgi_stdio.h>
int count = 0;
int main()
{
while(FCGI_Accept() >= 0)
{
int width = 0;
int height = 0;
char *query_string = getenv("QUERY_STRING");
if(query_string != NULL)
sscanf(query_string, "width=%d&height=%d", &width, &height);printf("Content type: text/html\n\n");
printf("width=%d,height=%d\n",width,height);
printf("pid=%d\n",getpid());
printf("count=%d\n",count);
count++;
}
return 0;
}
Makefile:
CROSS_PREFIX=arm-linux-CC=$(CROSS_PREFIX)gccSTRIP=$(CROSS_PREFIX)stripARMROOT=/home/armrootLIB=$(ARMROOT)/libINC=$(ARMROOT)/includeCFLAGS= -g -I$(INC) --std=gnu99 -W -Wall -O0SRC=$(shell find ./ -name '*.c')OBJ=$(SRC:%.c=%.o)DEP=$(SRC:%.c=%.dep)#LIBS:动态库LIBS=-lpthread -lfcgi -lz#SLIBS:静态库SLIBS=TARGET=fastcgi$(TARGET): $(DEP) $(OBJ)@echo -n linking...@$(CC) $(SLIBS) $(OBJ) -o $(TARGET) $(CFLAGS) -L$(LIB) $(LIBS)@echo done: $(TARGET).PHONY:stripstrip:$(TARGET)@if [ -e $(TARGET)_g ];then rm $(TARGET)_g;fi@cp $(TARGET) $(TARGET)_g@$(STRIP) $(TARGET)%.dep:%.c@$(CC) -MM $< $(CFLAGS) > $@__@if [ -e $@__ ];then echo -n $(dir $@) > $@;cat $@__ >> $@;rm $@__;fisinclude $(DEP)%.o:%.c@echo building $<@$(CC) -c $< -o $@ $(CFLAGS).PHONY:cleanclean:@for i in $(DEP);do if [ -e $${i} ];then rm $${i};fi;done@for i in $(OBJ);do if [ -e $${i} ];then rm $${i};fi;done@if [ -e $(TARGET) ];then rm $(TARGET);fi
将生成的文件拷贝到设备/www目录中
【4】启动服务器
lighttpd -f /etc/lighttpd.conf
-f 选项指定配置文件
-m 选项指定mod所在目录,默认为编译lighttpd时的prefix/lib,我这里就是/home/armroot/lib。
lighttpd会在初始化时启动配置文件中指定的fastcgi程序,这里是/www/fastcgi.fcgi
【5】测试
ps
523 root 0:00 lighttpd -f /etc/lighttpd.conf -m /opt/lighttpd
542 root 0:00 /www/fastcgi.fcgi
浏览器访问
http://192.168.1.127/fastcgi.fcgi?width=800&height=480
结果:
width=800,height=480
pid=542
count=0
width=800,height=480
pid=542
count=1
三、fastcgi编程实例
多线程请求例子
#include <string.h>
#include <syslog.h>
#include <alloca.h>
#include <fcgiapp.h>
#include <stdio.h>
#include <string>
#include <sstream>
#define THREAD_COUNT 20
#define LISTENSOCK_FILENO 0
#define LISTENSOCK_FLAGS 0
static int counts[THREAD_COUNT];
static void *doit(void *a)
{
int rc;
FCGX_Request request;
int err = FCGX_InitRequest(&request, LISTENSOCK_FILENO, LISTENSOCK_FLAGS);
if (err) { syslog(LOG_INFO, "FCGX_InitRequest failed: %d", err); return ; }
int count = 0;
for (;;)
{
rc = FCGX_Accept_r(&request);
if (rc < 0)
break;
FCGX_FPrintF(request.out,
"Content-type: text/html\r\n"
"\r\n"
"<title>FastCGI Hello! ");
// 输出计数
FCGX_FPrintF(request.out, "<p>Count:%d</p>", ++count);
// 输出数据长度
char *len = FCGX_GetParam("CONTENT_LENGTH", request.envp);
FCGX_FPrintF(request.out, "<p>Data length:%s\n</p>", (len ? len : "0"));
// 环境变量
auto envp = request.envp;
std::ostringstream output;
output << "<PRE>\n";
for (; *envp; ++envp)
{
output << *envp <<"\n";
}
output << "</PRE>\n";
// 输出
FCGX_PutS(output.str().c_str(), request.out);
// 获取body中数据,然后输出
if (len)
{
long length = -1;
try {
length = std::stol(len);
} catch (...){}
if (length > 0)
{
std::string data(length, '\0');
int size = FCGX_GetStr((char *)data.data(), length, request.in);
FCGX_FPrintF(request.out, "<p>read data size:%d</p>", size);
FCGX_PutStr(data.data(), data.size(), request.out);
}
}
sleep(2);
FCGX_Finish_r(&request);
}
return NULL;
}
int main(void)
{
int i;
pthread_t id[THREAD_COUNT];
int err = FCGX_Init(); /* call before Accept in multithreaded apps */
if (err) { syslog (LOG_INFO, "FCGX_Init failed: %d", err); return 1; }
for (i = 1; i < THREAD_COUNT; i++)
pthread_create(&id[i], NULL, doit, (void*)i);
doit(0);
return 0;
}
四、fcgiapp各个数据结构和函数含义
FCGX_Stream该struct定义了FastCGI流的状态。
流的状态是私有的,只能通过下面定义的程序访问。
FCGX_Request对一个请求的封装。可供访问的属性:
int requestId // 是否线程独立?
int role;
FCGX_Stream *in; // 在post方法中用来读取数据?
FCGX_Stream *out; // 输出应答内容
FCGX_Stream *err;
char **envp; // 系统 + Request的环境变量
int FCGX_Init() Initialize the FCGX library.
Call in multi-threaded apps before calling FCGX_Accept_r().
Returns 0 upon success.
int FCGX_InitRequest(FCGX_Request *request, int sock, int flags)
Initialize a FCGX_Request for use with FCGX_Accept_r().
参数sock是0(默认)或者是FCGX_OpenSocket()的返回值。
参数flags当前只支持FCGI_FAIL_ON_INTR(实现中并没有定义,都是使用0)。
int FCGX_Accept_r(FCGX_Request *request) 接受一个新的请求(多线程安全)。
一定要先调用一次FCGX_Init()。
成功放回0,失败返回-1。
结束request(并释放上一次调用中申请的内存)。创建输入,输出,错误流,
并分别赋值给(request中的)*in,*out,*err。创建包含参数的数据结构,并赋值给*envp,
可以通过getenv(如果将数据赋值给了environ)或FCGX_GetParam来访问。
不要一直保留指向envp数组或其中字符串的指针(例如FCGX_GetParam返回的结果),
因为在下一次调用FCGX_Finish或FCGX_Accept之后,它们都会被freed。
不要直接使用FCGX_Request,他的结构可能改变。
int FCGX_PutChar(int c, FCGX_Stream *stream) 将字符c写入stream。
成功返回c,失败返回EOF(-1)。
int FCGX_PutStr(const char *str, int n, FCGX_Stream *stream) 用于二进制输出。
从str开始,向stream中写入n个连续字节。对输出字节不做任何解释。
用于二进制输出。
成功返回写入的字节数,失败放回EOF(-1)。
int FCGX_PutS(const char *str, FCGX_Stream *stream) 用于输出字符串。
将已null结尾的字符串str写入stream,由FCGX_PutStr实现。
用于输出字符串。
成功返回写入的字节数,失败放回EOF(-1)
int FCGX_FPrintF(FCGX_Stream *stream, const char *format, ...) 将格式化字符串format写入stream。
成功返回写入的字节数,失败放回EOF(-1)
int FCGX_GetChar(FCGX_Stream *stream) 从输入读取一个字节。
返回读取的字节,如果到达输入结尾,则返回EOF(-1).
int FCGX_UnGetChar(int c, FCGX_Stream *stream) 将字符c推回输入流stream。
读取一个字符后再推回一个字符是确保可以实现的。
到达EOF后不能再执行推回操作。
如果成功返回c,否则返回EOF。
int FCGX_GetStr(char *str, int n, FCGX_Stream *stream) 从stream中读取n个连续字节到str中。
对读入字节不做任何解释。
返回读取的字节数,如果返回值小于n,说明已达到结尾。
char *FCGX_GetLine(char *str, int n, FCGX_Stream *stream) 从stream中读取n-1个连续字节到str中。
在读取n-1个字节前,如果碰到'\n'或EOF则停止,
结尾的‘\n’会被复制到str中。当复制完最后一个字节后,在str最后添加字节‘\0’。
如果读取的第一个字节就是EOF,那么返回NULL,否则返回str。
int FCGX_HasSeenEOF(FCGX_Stream *stream) 在读取stream时,如果检测到EOF,那么返回EOF,否则返回0。
请注意,FCGX_HasSeenEOF(s)可能会返回0,然后立即调用FCGX_GetChar(s)可能会返回EOF。
这个功能就像C函数feof,没有提供peek ahead功能。
五、Lighttpd 网页服务源码分析说明post数据lighttpd主程序不处理,而是交给动态执行模块fastcgi等来解析。
lighttpd处理静态页面要使用mod_staticfile.c插件。是lighttpd默认会加载的。
工作路径:server.document-root
如果需要配置fcgi,一般在modules.conf中使能include conf.di.conf比较合理。
六、参考
lighttpd fastcgi的搭建
https://www.cnblogs.com/fellow1988/p/6135756.html?utm_source=itdadao&utm_medium=referral
fastcgi 分布式
https://www.cnblogs.com/fellow1988/p/6139459.html
fcgiapp各个数据结构和函数含义
https://my.oschina.net/u/4274876/blog/3927213
FastCGI编程介绍
https://blog.csdn.net/lee244868149/article/details/45099723
在FastCGI应用程序中无法获取HTTP POST的主体
http://www.cocoachina.com/articles/109191
从HTML格式成功发布1MB文件,并且变量“ CONTENT_LENGTH”足够大:)但我不知道如何使用libfcgi访问POST请求的主体.这是我的HTML表单,效果很好.
<form action="/upload" enctype="multipart/form-data" method="POST">
<input type="test" name="text1" />
<input type="file" name="file1" />
<input type="submit" />
</form>
通过接受请求
int FCGX_Accept_r(FCGX_Request *request);
在 FCGX_Request 内部,我们有3个流:in,out,err. “ in”流中的标志为isReader == 1,其他的isReader == 0.
FCGX_Stream
该struct定义了FastCGI流的状态。流的状态是私有的,只能通过下面定义的程序访问。
FCGX_Request
对一个请求的封装。可供访问的属性:
int requestId // 是否线程独立?
int role;
FCGX_Stream *in; // 在post方法中用来读取数据?
FCGX_Stream *out; // 输出应答内容
FCGX_Stream *err;
char **envp; // 系统 + Request的环境变量
最佳答案
libfcgi提供了从输入流中读取的三个函数 FCGX_GetStr,FCGX_GetLine 和 FCGX_GetChar.
while (FCGX_GetStr(buf, sizeof(buf), request.in) > 0) {
/* ... */
}
您将需要解析 multipart/form-data 主体.
官网多线程的例子,(http://www.fastcgi.com/devkit/examples/threaded.c)
web服务选择lighttpd,采用fcgi组件技术扩展处理业务层相关推荐
- Web服务生存周期内发生的事件/Soap扩展的阶段/Soap扩展的步骤
客户端创建WEB服务代理类的一个新实例,该对象驻留在客户端所在的同一台计算机上. 客户端调用代理类上的方法. 客户端计算机上的ASP.NET框架的基础结构将WEB服务方法的参数序列化为SOAP消息,并 ...
- cookie和session、web服务工作原理、Apache配置php扩展、php简介
cookie和session: cookie和session区别:cookie数据是存在本地的,而session数据是存在服务端的,session比cookie更安全. cookie:用于http做会 ...
- Web服务集成CRM的应用
本文讲的是Web服务集成CRM的应用,[IT168 资讯]近年来,很多企业应用集成(EAI)供应商都提供专有的适配器和集成服务器工具集,试图解决企业应用集成过程中面临的挑战.虽然EAI解决方案很有效, ...
- 基于使用学习排序算法的Web服务学习的个性化的决策战略
摘要----为了从类似的服务列表中进行功能上的选择,用户往往需要根据多个QoS准则做出他们的决定,它们需要对目标服务.在这个过程中,不同的用户可能遵循不同的决策策略,有些是补偿性的,在这个补偿中在所有 ...
- IBM Lotus Domino 7 中的实用 Web 服务,第 1 部分: 什么是 Web 服务以及它们为何如此重要
Julian Robichaux, 开发人员, 独立顾问 Julian Robichaux 是专门研究 IBM Lotus Notes 和 Java 开发的软件开发人员和专业程序员.他擅长于各种与开发 ...
- IBM Lotus Domino 7 中的实用 Web 服务,第 1 部分: 什么是 Web 服务以及它们为何如此重要...
IBM Lotus Domino 7 中的实用 Web 服务,第 1 部分: 什么是 Web 服务以及它们为何如此重要 级别: 初级 Julian Robichaux, 开发人员, 独立顾问 2005 ...
- 一文讲透推荐系统提供web服务的2种方式
作者丨gongyouliu 编辑丨zandy 来源 | 大数据与人工智能(ID: ai-big-data) 推荐系统是一种信息过滤技术,通过从用户行为中挖掘用户兴趣偏好,为用户提供个性化的信息,减少用 ...
- 中国人工智能学会通讯——机器人组件技术在智能制造系统中的应用
摘要:随着工业4.0时代的到来,如何将传统工厂改造成为个性化.网络化.柔性生产的智能制造系统成为了当前的研究热点.本文从智能制造系统和智能机器人系统的相似性出发,构建了基于机器人组件技术的智能制造系统 ...
- Web服务安全性和SOA路线图的人为维度
在大多数非平凡的SOA环境中,很难跟踪系统之间不断发展的集成,除非有明确的发布和查找适当信息的方法. 概述IT环境,定义当前或将要连接的内容,是维护环境的先决条件. 缺少这种情况通常会导致" ...
最新文章
- 设计一个成绩分类 输入成绩 输出优秀_BenQ 明基 PD2720U 27寸 Thunderbolt3.0 专业设计显示器开箱评测...
- 使用sql server中的全文索引
- 三菱modbusRTU通讯实例_实例 | 三菱PLC接线图干货,FX5U模块硬件
- 【计算机组成原理】指令格式
- c++ primer plus中文版_如何成为一名厉害的C/C++程序员?
- 基于CUDA的TTI介质逆时偏移与ADCIGs提取
- java多条件不定条件查询
- vue 组件模板template定义时的注意事项
- Firefox-常用扩展
- 客户端压测server端计算qps以及不同延迟时间下响应数量所占百分比
- 【直观理解】粒子滤波 原理及实现
- “”和“”的你真的理解吗?
- C++ 使用正则表达式拆分字符串
- 深入理解Azure自动扩展集VMSS(3)
- Flutter监听网络变化
- atitit.软件开发--socket框架选型--netty vs mina j
- 【机器学习】金融风控评分卡建模全流程!
- BUUCTF——MISC(流量分析)
- 清华大学2001年机试-字符串排序-1066
- 【前辈经验】——前端职位描述
热门文章
- 中职计算机应用基础笔记,计算机应用基础_自考笔记+自考资料.doc
- python数字推盘游戏怎么显示步数_Python游戏开发:数字华容道
- 在线jsp版泰囧表情的生成器代码,不用PS也能恶搞。
- Inno Setup 语法
- 高级软件工程--平时作业汇总
- 第一次来学习开料软件的使用
- Lighting System Design UVA - 11400 照明系统设计 线性结构dp
- 竞品分析该如何写?竞品分析的维度有哪些?
- 『TinyOS』 nesC 1.1 语言参考手册
- linux remount命令详解,linux mount命令参数及用法详解