首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

琐事的学习——tinyhttpd简易WEB服务器

2013-04-20 
琐碎的学习——tinyhttpd简易WEB服务器tinyhttpd是一个超轻量型Http Server,使用C语言开发,全部代码只有502

琐碎的学习——tinyhttpd简易WEB服务器

tinyhttpd是一个超轻量型Http Server,使用C语言开发,全部代码只有502行。

我从sourceforge上下载后编译不通过,提示找不到libsocket,发现去掉对libsocket的依赖也没问题

httpd: httpd.cgcc -g -W -Wall -lsocket -lpthread -o httpd httpd.c#改为httpd: httpd.cgcc -g -W -Wall -lpthread -o httpd httpd.c

?执行cgi的函数中也有错误

#273行   execl(path, path, NULL);#改为   execl(path, query_string, NULL);

?编译运行./httpd就可以把web服务运行起来了。

?下面学习几段源代码

1,main函数初始化套接口监听并接收连接,针对每个连接开启线程去处理

int main(void){ int server_sock = -1; u_short port = 8080; 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);}

2,accept_request函数解析客户端请求,判断是请求静态文件还是cgi代码(通过请求类型以及参数来判定),如果是静态文件则将文件输出给前端,如果是cgi则进入cgi处理函数

3,execute_cgi函数负责将请求传递给cgi程序处理,服务器与cgi之间通过管道pip通信,首先初始化两个管道,并创建子进程去执行cgi函数

 if (pipe(cgi_output) < 0) {  cannot_execute(client);  return; } if (pipe(cgi_input) < 0) {  cannot_execute(client);  return; } if ( (pid = fork()) < 0 ) {  cannot_execute(client);  return; }

?子进程中,用刚才初始化的管道替换掉标准输入标准输出,将请求参数加到环境变量中,调用execl执行cgi程序获得输出。

if (pid == 0)  /* child: CGI script */ {  char meth_env[255];  char query_env[255];  char length_env[255];  dup2(cgi_output[1], 1);  dup2(cgi_input[0], 0);  close(cgi_output[0]);  close(cgi_input[1]);  sprintf(meth_env, "REQUEST_METHOD=%s", method);  putenv(meth_env);  if (strcasecmp(method, "GET") == 0) {   sprintf(query_env, "QUERY_STRING=%s", query_string);   putenv(query_env);  }  else {   /* POST */   sprintf(length_env, "CONTENT_LENGTH=%d", content_length);   putenv(length_env);  }  execl(path, query_string, NULL);  exit(0); }

?服务器"线程"继续将post的请求头发送给子进程(cgi程序),然后获取cgi程序的标准输出作为响应内容发送给客户端。

else {    /* parent */  close(cgi_output[1]);  close(cgi_input[0]);  if (strcasecmp(method, "POST") == 0)   for (i = 0; i < content_length; i++) {    recv(client, &c, 1, 0);    write(cgi_input[1], &c, 1);   }  while (read(cgi_output[0], &c, 1) > 0)   send(client, &c, 1, 0);  close(cgi_output[0]);  close(cgi_input[1]);  waitpid(pid, &status, 0); }

?502行代码都比较精炼,服务器在完成一些web功能外还处理了一些异常情况,500状态码cgi执行出错,404找不到文件错误之类的,开始以为putenv函数会设置个全局变量,当多用户访问的时候会互相影响,后来测试了一下发现设置的变量是互相隔离的,这些代码值得学习。

热点排行