【TinyHttpd学习笔记】500行的纯C语言Http服务器(含注释和webbench测试结果)

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(
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值