tinnyhttpd

源码阅读顺序

main —> startup —> accept_request —> excute_cgi

先看一个十分基本的服务端客户端模型代码

图片来源

https://baike.baidu.com/item/SOCKADDR_IN/3917215?fr=aladdin

在这里插入图片描述

工作流程

图片来自:

https://blog.csdn.net/sinat_19596835/article/

在这里插入图片描述

1.服务器启动,在指定端口或随机选取端口绑定httpd服务
2.收到一个HTTP请求时(listen端口accept的时候),派生一个线程运行
accept_request函数
3.取出HTTP请求中的method(GET或POST)和url。对于GET方法,如果有携带参数,则query_string指针指向url里 '?'后面的GET参数。
4.格式化url到path数组,表示浏览器请求的服务器文件路径,在tinyhttpd中服务器文件时在 htdocs文件夹下。当 url 以/结尾,或url是个目录,则默认在path中加上index.html.
5.如果文件路径合法,对于无参数的GET请求,直接输出服务器文件到浏览器,即用HTTP格式写到套接字上
7.建立两个管道,cgi_input和cgi_outputt,把STDIN重定向到cgi_input的读取端,关闭cgi_input的写入端的cgi_output的读取端,设置request_method的环境变量,GET的话设置query_string的环境变量,POST的换设置content_length的环境变量,这些环境变量都是为了给cgi脚本用,接着运行cgi程序。
9.在父进程中,关闭cgi_input的读取端和cgi_output的写入端,如果POST的话

首先来看main函数

int main(void)
{
   
//声明一个socket
 int server_sock = -1;
//默认端口号
 u_short port = 0;
//声明一个服务器
 int client_sock = -1;
//此数据结构用做bind、connect、recvfrom、sendto等函数的参数,指明地址信息(摘自百度百科)
 struct sockaddr_in client_name;
 int client_name_len = sizeof(client_name);
 pthread_t newthread;

 server_sock = startup(&port);
 printf("httpd running on port %d\n", port);
//持续监听,每收到一个请求就开启一个新线程
 while (1)
 {
   
  client_sock = accept(server_sock,
                       (struct sockaddr *)&client_name,
                       &client_name_len);
 //如果client_sock返回的是-1,则调用失败
  if (client_sock == -1)
   error_die("accept");
 //成功则创建新的线程,调用accept_request来处理,accept_request通过client_sock与客户机通讯
 /* accept_request(client_sock); */
 if (pthread_create(&newthread , NULL, accept_request, client_sock) != 0)
   perror("pthread_create");
 }
//关闭与客户端的连接,因为TCP/IP协议是无连接的
 close(server_sock);

 return(0);
}

start_up

/*服务器端套接字初始化设置*/  
int startup(u_short *port)  
{
     
    int httpd = 0;  
    struct sockaddr_in name;  

    httpd = socket(PF_INET, SOCK_STREAM, 0);//创建服务器端套接字,IPV4,TCP协议,返回server_socket的fd
    if (httpd == -1)  
        error_die("socket");  
    memset(&name, 0, sizeof(name));//初始化name的内存  
    name.sin_family = AF_INET;//地址簇  
    name.sin_port = htons(*port);//指定端口  
    name.sin_addr.s_addr = htonl(INADDR_ANY);//通配地址  
    if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0)//绑定到指定地址和端口  
        error_die("bind");  
    if (*port == 0)  /* if dynamically allocating a port *///动态分配一个端口  
    {
     
        int namelen = sizeof(name);  
        
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值