【 原理 】 一般来说,HTTP Server 也是我们常说的Web服务器,大名鼎鼎的 Apache,还是微软的 IIS (Internet Information Server),开源领域的有 Lighttpd 和最近风头正劲的 Nginx 都是典型的Web服务器。最近想想能不能做一个Web服务器,就提供简单的功能,但是速度很快,能够作为一个专门处理 HTML/CSS/JS/Image 的Web服务器,那样能够让静态资源文件迅速的被访问到,如果有反向代理功能就更帅了,当然了,要是有Cache功能啥的,并且能够编写自定义插件(扩展)就很完美了。。。YY中。。。
基于这个思想,我就花十天时间使用标准C写了一个千行代码小型的HTTP Server,当然目前还不具有反向代理和扩展功能,只是能够简单的支持 HTML/CSS/JS/Image 静态资源文件的访问。HTTP Server 的名字叫做 tmhttpd - TieMa (Tiny&Mini) HTTP Server,小巧,代码少,执行速度快,目前具有的功能包括:
Support GET/HEAD method
The common MIME types.
Support Self custom default index page
Directory listings.
Support access log
Support Self custom port and max clients
Use fork mode accept new conntion
Support daemon type work
more ..
目前已经发布了 tmhttpd-1.0.0_alpha 版本,包括for Unix/Linux (在 Ubuntu/Fedoar/FreeBSD 下编译通过) 和 在cygwin环境下编译的 for Windows 版本,下面地址有下载:
Unix/Linux:
Windows:
下面大致来聊聊怎么写一个 HTTP Server,先看看一个HTTP请求的流程:
大致就是 客户端的浏览器(IE、Firefox、Opera、Lynx、Curl、Robot ...) 访问到Web服务器的端口(一般是80),然后端口接受到请求后开始解析请求,如果请求不正确或者非法则直接返回指定的错误代码(可以参考 RFC 1945),如果请求合法,那么就查找相应用户请求的文件,把文件读取后发送给客户端,关闭连接,请求结束。
【 实现 】
贴部分tmhttpd核心代码来描述这个过程:
/** * 初始化服务器端的Socket连接,等待连接,连接成功后fork新进程处理 * */ static void InitServerListen( unsigned int port, unsigned int max_client ){ int serversock, clientsock; struct sockaddr_in server_addr, client_addr; char currtime[32]; /* Create the TCP socket */ if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){ die("Failed to create socket"); } /* Construct the server sockaddr_in structure */ memset(&server_addr, 0, sizeof(server_addr)); /* Clear struct */ server_addr.sin_family = AF_INET; /* Internet/IP */ server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Incoming addr */ server_addr.sin_port = htons(port); /* server port */ /* Bind the server socket */ if (bind(serversock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0){ die("Failed to bind the server socket"); } /* Listen on the server socket */ if (listen(serversock, max_client) < 0){ die("Failed to listen on server socket"); } /* Print listening message */ getdate(currtime); fprintf(stdout, "[%s] Start server listening at port %d ...\n", currtime, port); fprintf(stdout, "[%s] Waiting client connection ...\n", currtime); /* Run until cancelled */ while (1){ unsigned int clientlen = sizeof(client_addr); memset(currtime, 0, sizeof(currtime)); getdate(currtime); /* Wait for client connection */ if ((clientsock = accept(serversock, (struct sockaddr *) &client_addr, &clientlen)) < 0){ die("Failed to accept client connection"); } /* Use child process new connection */ if ( fork() == 0 ){ HandleClient(clientsock, client_addr); } else { wait(NULL); } /* Not use close socket connection */ close(clientsock); } } %3
|
阅读(2692) | 评论(0) | 转发(0) |