1、项目简介
前段时间阅读了源码tinyHttpd, TinyHttpd—-超轻量型Http Server源码分析
然后基于这个实现一个查询天气的功能,以及该服务器能够连接数据库的功能。
2、项目的背景知识
(1)该项目在Linux系统下开发的,熟悉Linux的开发环境。
(2)熟悉掌握多线程编程
(3) 熟悉掌握网络协议中的HTTP以及网络编程
(4) 熟悉mysql的基本命令
(5)了解mysql的C库
(6) 熟悉python语言、shell脚本语言以及CGI脚本
3、项目的原理图
注 :fork进行管道通信时,input和output针对cgi脚本来说的,input管道用于向cgi脚本输入数据,所以关闭input[1]写端
output管道用于cgi脚本向外输出数据,所以关闭output[0]读端。
从以上原理图可以看出该项目的主体框架流程,再结合tinyHttp开源项目的分析,可以很容易的理解这个项目。
4、项目系统的框架
(1)http服务器:http.h http.c main.c
(2)conf模块:服务器的配置文件
(3)log模块:日志
(4)lib模块:存放mysql的C库
(5)sql模块:实现连接数据库
(6)wwwroot模块:实现cgi脚本以及html文件
(7)plugin模块:实现控制服务器的脚本
5、模块功能的实现
在tinyHttpd这个项目中我已经分析过大概流程,下面是博客地址
http://blog.csdn.net/wenqiang1208/article/details/74788798
接下来 就着重看CGI脚本的实现,以及mysql
5.1、CGI
CGI 目前由NCSA维护,NCSA定义CGI如下:CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如:HTTP服务器,提供同客户端HTML页面的接口。
CGI程序可以是Python脚本,PERL脚本,SHELL脚本,C或者C++程序等。
下图是CGI的架构图
该项目的cgi脚本是python编写的访问查看天气的脚本,前段时间用python写过这个。
pytho实现天气查询
5.2、连接数据库功能
注:该功能就是为了测试连接数据库,建立了一个数据库class,表student_info包括name,sex,school,id 四个信息
该项目是下载了mysql的C库,方便查看接口,容易理解
5.3 Makefile
makefile也是比较重要的一块,
其中的编译cgi脚本的makefile 第一次使用 ,感觉特别好,
解释下那个for循环 i 从变量中取出路径,然后执行循环体,进入该目录下执行cgi的makefile,然后再回到当前目录下,继续执行for循环。
其中的执行语句前面的@语句,是为了在终端不显示出执行此命令的信息。
bin=httpd
cc=gcc
obj=http.o main.o
LDFLAGS=-lpthread #-static
FLAGS=-D_DEBUG_
CGI_PATH=sql wwwroot/cgi-bin
.PHONY:all
all:${bin} cgi
${bin}:${obj}
@${cc} -o $@ $^ ${LDFLAGS} -g
@echo "[linking] [$@] to [$^] .....done"
%.o:%.c
@gcc -c -g $< #${FLAGS}
@echo "[completing] [$@] to [$^]......done"
#编译cgi脚本
cgi:
@for i in `echo$(CGI_PATH)`;\
do\
cd $$i;\
make;\
cd -;\
done
.PHONY:output
output:
@mkdir -p output/wwwroot/cgi-bin
@cp -rf log output
@cp -rf conf output
@cp -r wwwroot/index.html output/wwwroot/
@cp wwwroot/cgi-bin/math_cgi output/wwwroot/cgi-bin
@cp sql/insert_cgi output/wwwroot/cgi-bin
@cp sql/select_cgi output/wwwroot/cgi-bin
@cp -rf sql/lib output
@cp httpd output
@cp plugin/ctl_server.sh output
@echo "output project ....done"
.PHONY:clean
clean:
@rm -rf ${bin} *.o output
@for i in `echo $(CGI_PATH)`;\
do\
cd $$i;\
make clean;\
cd -;\
done
@echo "clean project ....done"
5.4 控制脚本
第一次控制脚本,解释一下该脚本,
(1)先检查是否导入库,if 判断
(2) 然后判断执行改脚本的参数 是否正确
(3) 再case 语句判断执行脚本的哪个参数,有四种
(4) 四种参数,对应四种方法。
#!/bin/bash
#注该脚本在output目录下运行
ROOT_PATH=$(pwd)
LIB=$ROOT_PATH/lib/lib
BIN=$ROOT_PATH/httpd
CONF=$ROOT_PATH/conf/server.conf
id=''
proc=$(basename $0)
function usage()
{
printf "Usage :%s [start(-s)] [ stop(-t) ] [ restart(-r)] [ status(-ss)]\n" "$proc"
}
function server_status()
{
#pidof 查看服务
server_bin=$(basename $BIN)
id=$(pidof $server_bin)
if [ ! -z "$id" ];then
return 0
else
#id为空
return 1
fi
}
function service_start()
{
if ! server_status ;then
ip=$(awk -F: '/^IP/{print $NF}' $CONF)
port=$(awk -F: '/^PORT/{print $NF}' $CONF)
$BIN $ip $port
echo "start...done"
else
echo "server is already running : $id"
fi
}
function service_stop()
{
if server_status ;then
kill -9 $id
echo "stop ....done"
else
echo "server is not running,please running first!"
fi
}
function service_restart()
{
if server_status ;then
service_stop
fi
service_start
}
function service_status()
{
if server_status;then
echo "server is running: $id"
else
echo "server is not running"
fi
}
#先导入库
if [ -z "$LD_LIBRARY_PATH" ];then
export "LD_LIBRARY_PATH=$LIB"
fi
#判断是否用对,参数是否为0
if [ $# -eq 0 ];then
usage
exit 1
fi
case $1 in
start | -s)
service_start
;;
stop | -t)
service_stop
;;
restart | -r)
service_restart
;;
status | -ss)
service_status
esac
总结
(1) 在编写该项目之前 就已经看了开源项目tinyHttp ,就容易比较理解
(2) 在编写Makefile,链接mysql的C库,遇到很多的问题,库找不到以及库的引用不正确。
(3) 在编译时,遇到段错误,使用gdb 调试,找出错误。
(4)在实现cgi脚本与子进程交互时,获取不到传递的参数,使用telnet,自定义发送方法,查找错误。
(4) 在编写http服务器,需要对网络协议http 要有足够的了解,才会少走弯路。
项目已托管到GitHub上,
https://github.com/WenQiangW/HttpServer