最近在学习HTTP服务器设计的相关知识,流连于网海之中,邂逅了Kevin Lynx老兄的博文《实现自己的HTTP Server》 链接如下:
http://www.cppblog.com/kevinlynx/archive/2008/07/30/57521.html
读了之后,觉得写得很好,原理和实现部分都阐述得浅显易懂。在看过文章后,又down了他写的代码下了看,今晚调试了一个最简单的HTTP Server的C实现的代码。对HTTP的原理总算有了些感性的认识,也才基本明白解析HTTP报文是怎么一回事,感觉无非就是解析一些字符串(现在学习的比较浅,莫嘲笑)。主要关键是了解HTTP报文的格式看代码就很清楚了。
代码还是得亲自去调试的,这和只是看一看还是有很大区别的!
在程序所在目录下建立一个最简单的HTML文件 index.html 。
内容为:
<head><head><title>index.html</title></head><body>index.html</body>
即可。
运行程序后,在你的浏览器中输入: http://localhost:8080/index.html 即可看到上面HTML文件的内容。这就完成了一个最基础的HTTP Server的功能了哦!同时,Kevin Lynx老兄还给出了一个完整的httpd library,正在学习了解中!非常感谢Kevin Lynx!
下面附上这个Server实现的代码:
/** @file sample_httpd.c @author Kevin Lynx @brief sample httpd, just for testing purpose. */ #include <winsock2.h> #include <stdio.h> void http_response( SOCKET con, const char *request ) { /* get the method */ char *token = strtok( request, " " ); char *uri = strtok( 0, " " ); //char *uri1 = strtok( 0, " " ); char file[64]; sprintf( file, ".%s", uri ); { /* load the file content */ FILE *fp = fopen( file, "rb" ); if( fp == 0 ) { /* response 404 status code */ char response[] = "HTTP/1.1 404 NOT FOUND\r\n\r\n"; send( con, response, strlen( response ), 0 ); } else { /* response the resource */ /* first, load the file */ int file_size ; char *content; char response[1024]; fseek( fp, 0, SEEK_END ); file_size = ftell( fp ); fseek( fp, 0, SEEK_SET ); content = (char*)malloc( file_size + 1 ); fread( content, file_size, 1, fp ); content[file_size] = 0; sprintf( response, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s", file_size, content ); send( con, response, strlen( response ), 0 ); free( content ); } } } int main() { WSADATA wd; int ret; SOCKET s; ret = WSAStartup( MAKEWORD( 2, 0 ), &wd ); if( ret < 0 ) { fprintf( stderr, "winsock startup failed\n" ); exit( -1 ); } s = socket( AF_INET, SOCK_STREAM, 0 ); { /* bind and listen */ struct sockaddr_in addr; memset( &addr, 0, sizeof( addr ) ); addr.sin_family = AF_INET; addr.sin_port = htons( 8080 ); addr.sin_addr.s_addr = inet_addr( "0.0.0.0" ); ret = bind( s, (struct sockaddr*)&addr, sizeof( addr ) ); if( ret < 0 ) { fprintf( stderr, "bind failed\n" ); closesocket( s ); exit( -1 ); } ret = listen( s, 1024 ); if( ret < 0 ) { fprintf( stderr, "listen failed\n" ); closesocket( s ); exit( -1 ); } } { SOCKET con = accept( s, 0, 0 ); /* recv request */ char request[1024] = { 0 }; ret = recv( con, request, sizeof( request ), 0 ); printf( request ); http_response( con, request ); closesocket( con ); } closesocket( s ); WSACleanup(); return 0; }