源码分析之tinyhttpd(一)

来源:互联网 发布:网络远程正规吗 编辑:程序博客网 时间:2024/05/29 19:59

tinyhttpd是一个十分简单的http多线程服务器,通过详细分析500行左右的代码,对http请求和响应有一个简单的理解。

http://sourceforge.net/projects/tinyhttpd/

首先,从main函数开始:

<pre name="code" class="cpp">int main(void){int server_sock = -1;u_short port = 0;int client_sock = -1;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);if (client_sock == -1)error_die("accept");/* accept_request(client_sock); */if (pthread_create(&newthread , NULL, accept_request, client_sock) != 0)perror("pthread_create");}close(server_sock);return(0);}
3-8行:变量初始化工作

10行:startup函数,

int startup(u_short *port){int httpd = 0;struct sockaddr_in name;httpd = socket(PF_INET, SOCK_STREAM, 0);if (httpd == -1)error_die("socket");memset(&name, 0, sizeof(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);if (getsockname(httpd, (struct sockaddr *)&name, &namelen) == -1)error_die("getsockname");*port = ntohs(name.sin_port);}if (listen(httpd, 5) < 0)error_die("listen");return(httpd);}

传入参数:*port,由于main函数中port为0,未指定绑定端口号,需要系统分配。

4行:struct socketaddr_in,是一个表示使用地址族、端口和网络地址的结构体。

struct sockaddr_in{short sin_family;/*Addressfamily一般来说AF_INET(地址族)PF_INET(协议族)*/ unsigned short sin_port;/*Portnumber(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)*/ struct in_addr sin_addr;/*Internetaddress*/ unsigned char sin_zero[8];/*Samesizeasstructsockaddr没有实际意义,只是为了 跟SOCKADDR结构在内存中对齐*/};

6行:初始化服务器socket。使用Internet协议族,protocol family Internet;SOCK_STREAM对应TCP协议,SOCK_DGRAM对应UDP协议,SOCK_RAW是面向底层协议的。

11行:htons(),将主机字节顺序转换为网络字节顺序。h,host;n,network;s,short(2Bytes);l:long(4Bytes)。另外还有htonl(),ntohs(),ntohl()函数。

12行:INADDR_ANY:0.0.0.0,表示所有地址,绑定监听本机的所有IP地址。

13行:进行绑定,httpd与name对应的地址端口绑定。

15-21行:由于*port=0,系统会自动分配一个端口,使用getsockname获取。注意:必须在bind成功后才能获取。

22行:开始监听,后一个参数5表示决定了未完成队列和已完成队列中连接数目之和的最大值。

0 0
原创粉丝点击