Tinyhttpd源码分析!简单的HTTP请求处理服务器!!!

本文介绍了Tinyhttpd这个小型HTTP服务器的源码分析,涉及CGI、POSIX线程、进程和管道等知识点。通过阅读源码,了解HTTP请求处理流程,包括接受请求、执行CGI、文件服务等关键函数的功能。文章提供了一个学习Linux网络编程基础项目的参考路径。
摘要由CSDN通过智能技术生成

Tinyhttpd源码分析!

Github地址HERE

最近两天看了小项目,在博客中记录下学习笔记!!!

tinyhttpd是一个简易的HTTP服务器,可以处理POST/GET请求,使用CGI技术实现简单的网页表单提交。代码可以在Linux上运行,涉及POSIX 线程\进程\管道\字符串处理等知识点。是学习Linux网络编程的基础项目。

代码经过简单修改可以直接在Linux系统上make,需要注意的点:
1、使用Linux系统需安装perl和perl-CGI,CGI程序也可以使用Python脚本、SHELL脚本、C和C++;

2、htdocs文件夹中的*.html文件权限设置成644/444等,总之不可执行,*.cgi文件设置成755,可执行;

每个函数的作用:
accept_request: 处理从套接字上监听到的一个 HTTP 请求,进行HTTP请求头处理,对method与url等进行解析。
bad_request: 返回给客户端这是个错误请求,HTTP 状态吗 400 BAD REQUEST。
cat: 读取服务器上某个文件写到 socket 套接字。
cannot_execute: 主要处理发生在执行 cgi 程序时出现的错误。
error_die: 把错误信息写到 perror 并退出。
execute_cgi: 运行 cgi 程序的处理,也是个主要函数。
get_line: 读取套接字的一行,把回车换行等情况都统一为换行符结束。
headers: 把 HTTP 响应的头部写到套接字。
not_found: 主要处理找不到请求的文件时的情况。
sever_file: 调用 cat 把服务器文件返回给浏览器,内部调用headers()函数和cat()函数。
startup: 初始化 httpd 服务,包括建立套接字,绑定端口,进行监听等。

unimplemented: 返回给浏览器表明收到的 HTTP 请求所用的 method 不被支持。

建议源码阅读顺序: main(); startup(); accept_request(); execute_cgi()。

(1)服务器启动,在指定端口或随机选取端口绑定 httpd 服务。
(2)收到一个 HTTP 请求时(其实就是 listen 的端口 accpet 的时候),派生一个线程运行 accept_request 函数。
(3)取出 HTTP 请求中的 method (GET 或 POST) 和 url,。对于 GET 方法,如果有携带参数,则 query_string 指针指向 url 中 ? 后面的 GET 参数。
(4)cpoy url 到 path 数组,表示浏览器请求的服务器文件路径,在 tinyhttpd 中服务器文件是在 htdocs 文件夹下。当 url 以 / 结尾,或 url 是个目录,则默认在 path 中加上 index.html,表示访问主页。
(5)如果文件路径合法,对于无参数的 GET 请求,直接输出服务器文件到浏览器,即用 HTTP 响应头格式写到套接字上,跳到serve_file()函数。其他情况(带参数 GET,POST 方式,url 为可执行文件),则调用 excute_cgi 函数执行 cgi 脚本。
(6)读取整个 HTTP 请求并丢弃,如果是 POST 则找出 Content-Length. 把 HTTP 200 ;状态码写到套接字。
(7)建立两个管道,cgi_input 和 cgi_output, 并 fork 一个进程。
(8)在子进程中,把 STDOUT 重定向到 cgi_output 的写入端,把 STDIN 重定向到 cgi_input 的读取端,关闭 cgi_input 的写入端 和 cgi_output 的读取端,设置 request_method 的环境变量,GET 的话设置 query_string 的环境变量,POST 的话设置 content_length 的环境变量,这些环境变量都是为了给 cgi 脚本调用,接着用 execl 运行 cgi 程序。

(9)在父进程中,关闭 cgi_input 的读取端 和 cgi_output 的写入端,如果 POST 的话,把 POST 数据写入 cgi_input,已被重定向到 STDIN,读取 cgi_output 的管道输出到客户端,该管道输入是 STDOUT。

管道图解:(画的是真的丑


Linux下make 运行:




注释版代码如下:
/* J. David's webserver */
/* This is a simple webserver.
 * Created November 1999 by J. David Blackstone.
 * CSE 4344 (Network concepts), Prof. Zeigler
 * University of Texas at Arlington
 */
/* This program compiles for Sparc Solaris 2.6.
 * To compile for Linux:
 *  1) Comment out the #include <pthread.h> line.
 *  2) Comment out the line that defines the variable newthread.
 *  3) Comment out the two lines that run pthread_create().
 *  4) Uncomment the line that runs accept_request().
 *  5) Remove -lsocket from the Makefile.
 */
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>
#include <strings.h>
#include <string.h>
#include <sys/stat.h>
#include <pthread.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdint.h>

#define ISspace(x) isspace((int)(x))

#define SERVER_STRING "Server: jdbhttpd/0.1.0\r\n"
// 标准输入流  标准输出流  标准错误流
#define STDIN   0
#define STDOUT  1
#define STDERR  2
// Http请求,后续主要是处理这个头
//
// GET / HTTP/1.1
// Host: 192.168.1.103:4000
// Connection: keep-alive
// Upgrade-Insecure-Requests: 1
// User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*; q = 0.8
// Accept - Encoding: gzip, deflate, sdch
// Accept - Language : zh - CN
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值