基于C+Spawn-fcgi实现一个最简单的WebServer.
spawn-fcgi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| [安装b包]
spawn-fcgi-1.6.3-1.el6.x86_64
fcgi-devel-2.4.0-12.el6.x86_64
fcgi-2.4.0-12.el6.x86_64
[spawn-fcgi关键参数]
Usage: spawn-fcgi [options] [-- <fcgiapp> [fcgi app arguments]]
spawn-fcgi v1.6.3 (ipv6) - spawns FastCGI processes
Options:
-f <path> 【fcgi的应用程序,需要绝对路径】filename of the fcgi-application (deprecated; ignored if
<fcgiapp> is given; needs /bin/sh)
-d <directory> 【在产卵子进程之前,先chdir到指定目录】chdir to directory before spawning
-a <address> 【绑定监听IP地址】bind to IPv4/IPv6 address (defaults to 0.0.0.0)
-p <port> 【绑定TCP端口】bind to TCP-port
-s <path> 【绑定关连到一个unix套接字】bind to Unix domain socket
-M <mode> 【更改Unix套件字的模式】change Unix domain socket mode
-C <children> 【仅PHP可用,设定PHP-CGI的子进程数量】(PHP only) numbers of childs to spawn (default: not setting
the PHP_FCGI_CHILDREN environment variable - PHP defaults to 0)
-F <children> 【fork出来的CGI子进程数量,默认是1】number of children to fork (default 1)
-P <path> 【产卵出来的进程PID文件存储路径,在no-fork模式中被忽略】name of PID-file for spawned process (ignored in no-fork mode)
-n 【不fork子进程,针对daemon模式】no fork (for daemontools)
-v show version
-?, -h show this help
(root only) ------Root账号可用参数
-c <directory> 【chroot安全】chroot to directory
-S create socket before chroot() (default is to create the socket
in the chroot)
-u <user> change to user-id
-g <group> change to group-id (default: primary group of user if -u
is given)
-U <user> change Unix domain socket owner to user-id
-G <group> change Unix domain socket group to group-id
|
cgi部分
tiny-cgi.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| #include <stdio.h>
int main(void) {
int count = 0;
//fastcgi accecpt
while (FCGI_Accept() >= 0) {
// http header
printf("HTTP/1.0 200 OK\r\n");
// http header
printf("Content-Type: text/html; charset=utf-8\r\n");
printf("Server: ByCGI\r\n");
// content body
printf("\r\n");
printf("Hi,Man, I print by cgi program!!<br/>\r\n");
printf("Server Name : %s <br/>", getenv("SERVER_NAME"));
printf("Count number : %d ", count++);
}
return 1;
}
|
CGI编译的一些问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| [编译错误]
[clark@mac clang]$ gcc tiny-cgi.c -o tiny-cgi
/tmp/ccvVMqJM.o: In function `main':
tiny-cgi.c:(.text+0x1f): undefined reference to `FCGI_printf'
tiny-cgi.c:(.text+0x2e): undefined reference to `FCGI_printf'
tiny-cgi.c:(.text+0x3d): undefined reference to `FCGI_printf'
tiny-cgi.c:(.text+0x4c): undefined reference to `FCGI_printf'
tiny-cgi.c:(.text+0x5b): undefined reference to `FCGI_printf'
/tmp/ccvVMqJM.o:tiny-cgi.c:(.text+0x7b): more undefined references to `FCGI_printf' follow
/tmp/ccvVMqJM.o: In function `main':
tiny-cgi.c:(.text+0x98): undefined reference to `FCGI_Accept'
collect2: ld returned 1 exit status
[查看fcgi安装情况]
[clark@mac clang]$ rpm -qa|grep fcgi
spawn-fcgi-1.6.3-1.el6.x86_64
fcgi-devel-2.4.0-12.el6.x86_64
fcgi-2.4.0-12.el6.x86_64
[fcgi-devel包信息]
[clark@mac clang]$ rpm -ql fcgi-devel
/usr/include/fastcgi.h
/usr/include/fcgi_config.h
/usr/include/fcgi_stdio.h
/usr/include/fcgiapp.h
/usr/include/fcgimisc.h
/usr/include/fcgio.h
/usr/include/fcgios.h
/usr/lib64/libfcgi++.so
/usr/lib64/libfcgi.so ---------- 连接加上
...
[FCGI相关函数头部信息所在]
[clark@mac clang]$ grep FCGI_printf /usr/include/* -r
/usr/include/fcgi_stdio.h:DLLAPI int FCGI_printf(const char *format, ...);
/usr/include/fcgi_stdio.h:#define printf FCGI_printf
[缺少相关的连接库,缺少fcgi.so,增加链接(-lfcgi),解决]
[clark@mac clang]$ gcc tiny-cgi.c -o tiny-cgi -lfcgi
[clark@mac clang]$ ll tiny-cgi
-rwxrwxr-x 1 Terry Terry 7246 Aug 21 13:49 tiny-cgi
|
调试
利用spawn-fcgi程序启动fcgi脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| [clark@mac clang]$ spawn-fcgi -f ./tiny-cgi -p 12580 -F 5 -u nginx -g nginx -P /tmp/tiny-cgi.pid
spawn-fcgi: child spawned successfully: PID: 11208
spawn-fcgi: child spawned successfully: PID: 11209
spawn-fcgi: child spawned successfully: PID: 11210
spawn-fcgi: child spawned successfully: PID: 11211
spawn-fcgi: child spawned successfully: PID: 11212
[clark@mac clang]$ cat /tmp/tiny-cgi.pid
11208
11209
11210
11211
11212
[clark@mac clang]$ pstree Aup|grep cgi
[kill掉]
[clark@mac clang]$ cat /tmp/tiny-cgi.pid |xargs -n 1 kill -15
|
bash shell 管理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
| #!/bin/bash
#
# 利用Spawn-CGI进行C编译的CGI相关管理
#
# Set up a default search path.
PATH="/sbin:/usr/sbin:/bin:/usr/bin"
export PATH
# Setting
user=www
group=www
pid_file=/tmp/tiny-cgi.pid
cgi_bin=./tiny-cgi
port=19000
process_num=2
# Cmd
sh="spawn-fcgi -f $cgi_bin -p $port -F $process_num -u $user -g $group -P $pid_file"
# exec
#printf "共计 $# 个变量, \$@代表以IPS分隔的字符串: $@, \$*代表每个参数清单:$* \n";
case "$1" in
"start")
echo "Start spawn-cgi child process...";
$sh
;;
"stop")
echo "Stop spawn-cgi child process..."
cat $pid_file|xargs -n 1 kill -15;
ps -ef|grep "$(basename "$cgi_bin")"|grep -v grep;
;;
"restart" )
exec_result=0
# 有无cgi运行
if [ `ps -ef|grep $(basename "$cgi_bin")|grep -v "grep"|wc -l` -gt 0 ]; then
$0 stop
fi;
if [ "$exec_result" == "0" ]; then
$0 start
else
echo "Stop faild... Can not go on start!!"
fi
;;
*)
echo "Usage $0 start|stop|restart.";
;;
esac
|
请求结果
由于开启的是两个CGI进程,请求被轮询的丢给CGI处理,最终的结果就是,请求两次有一次
1
2
3
4
5
6
7
8
9
10
| [Response]
HTTP/1.1 200 OK
Date: Mon, 21 Aug 2017 08:20:03 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Server: ByCGI
Content-Length: 85
Hi,Man, I print by cgi program!!<br/>
Server Name : localhost <br/>Count number : 5
|
参考
- Nginx + CGI/FastCGI + C/Cpp <涵盖spawn-fcgi部分>
- 什么是CGI、FastCGI、PHP-CGI、PHP-FPM、Spawn-FCGI