目录
Tinyhttpd是一个小型的http服务器实现,代码仅仅500行,我在大致过了一下unix环境编程之后就想找一个web服务器来练练手,这个就作为俺第一个web方向的小项目吧。
看完这个代码后准备研究一下muduo库、Nginx和Redis,上天保佑我能在秋招实习之前看完吧。
官方源文件:http://tinyhttpd.sourceforge.net/
注释后代码链接:https://github.com/Supredan/DanTinyHttpd
看完有帮助github上帮我点个star哦~磕头了!
参考了:https://github.com/qiyeboy/SourceAnalysis/tree/master/TinyHttpd,和https://github.com/cbsheng/tinyhttpd
感谢!
阅读这个程序需要UNIX编程的基础,包括socket相关API,多线程(虽然在Linux下没有用到),多进程和进程间通信,HTTP基础知识。
从main函数开始
int main(void)
{
//在Ubuntu 16.04下运行,进行了修改
int server_sock = -1;//服务器端fd
u_short port = 0;//端口号,传0则随机绑定端口
int client_sock = -1;//客户端fd
struct sockaddr_in client_name;
socklen_t client_name_len = sizeof(client_name);
pthread_t newthread;
server_sock = startup(&port);//返回一个服务器端socket
printf("httpd running on port %d\n", port);
//不断循环接收连接请求
while (1)
{
client_sock = accept(server_sock,
(struct sockaddr *)&client_name,
&client_name_len);//阻塞等待连接
if (client_sock == -1)
error_die("accept");
//本来是线程版本,按照Linux注释修改,现在同一时间只能处理一个请求
//应该是1999年Linux还没有线程的功能吧。。。
//accept_request(&client_sock);//http请求的具体处理函数
if (pthread_create(&newthread , NULL, accept_request, (void *)&client_sock) != 0)
perror("pthread_create");
}
//关闭服务器端socket
close(server_sock);
return(0);
}
可以看到整个过程非常简单,注释写的很清楚了。
用startup(&port);
函数初始化后,处理的逻辑由accept_request(&client_sock);
实现。
初始化函数startup(&port)
这个函数开启一个socket来监听特定端口的网络请求,输入参数为0时则动态生成一个端口号,否则用输入的参数做端口号。
int startup(u_short *port)
{
int httpd = 0;
int on = 1;
struct sockaddr_in name;
httpd = socket(PF_INET, SOCK_STREAM, 0);//创建socket
if (httpd == -1)//创建失败处理
error_die("socket");
memset(&name, 0, sizeof(name));//清空name内容
//设置name的参数,分别代表采用IPv4、端口的主机字节序转网络字节序、地址
name.sin_family = AF_INET;
name.sin_port = htons(*port);
name.sin_addr.s_addr = htonl(INADDR_ANY);
//设置端口复用
if ((setsockopt(httpd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0)
{
error_die("setsockopt failed");
}
//绑定socket和地址
if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0)
error_die("bind");
//如果传入参数为0,则动态分配端口,获取端口号并传出
if (*port == 0) /* if dynamically allocating a port */
{
socklen_t namelen = sizeof(name);
if (getsockname(