轻量级嵌入式web服务器 --libhttpd

2019-07-13 04:24发布

一、嵌入式web服务器
      在网上找了很多关于嵌入式web server的资料,比如shttpd、appweb、boa、go ahead、server等等, 但都有网友反映移植不方便、资源要求高等等。如果用于运行ucLinux的arm9上,就没有什么问题,而用于运行ucOS的arm7上,则有很多限制,需要进行很多的移植工作,今天找到一个叫做LibHttpd的,采用ANSIC编写,仅从介绍上来看,非常适合arm7的嵌入式设备使用。       嵌入式设备中使用Web server的主要目的就是用来进行参数设置,使用这种方式,有很多优点:       1、可以给用户熟悉的用户界面,减少用户的学习负担。       2、具有B/S方式的优点,不再需要在每个客户机上安装配套的软件,不需要在客户机上升级软件,也不再需要支持由于客户机环境带来的种种问题。       LibHttpd是一个开源轻量级嵌入式Web server,LibHttpd实现了下述功能:       1)实现了HTTP的子集;       2)使用表格技术自动处理Html Form数据;       3)产生的内容既可以是静态的网页,也可以是调用C函数动态产生的(callback);       LibHttpd提供API,利用这些API,用户可以很方便地将自己的Web内容加入到程序当中。
 二、libhttpd中带有英文的使用手册,也增加了使用实例源码,在编程中可以做一个很好的模板: #include "config.h" #include #include #include #ifdef _WIN32 # include #else # include #endif #include "httpd.h" /* ** This is a static page of HTML. It is loaded into the content ** tree using httpdAddStaticContent( ). */ #define test1_html "This is just a test" #define ember_code1 "printf("This is from ember in process %d ",getpid());" #define ember_code "load "/usr/local/nk/www/content.lib"; dispatchWebPage("/index.html");" /* ** Below are 2 dynamic pages, each generated by a C function. The first ** is a simple page that offers a little dynamic info (the process ID) ** and the setups up a test link and a simple form. ** ** The second page processes the form. As you can see, you can access ** the form data from within your C code by accessing the symbol table ** using httpdGetVariableByName() (and other similar functions). You ** can also include variables in the string passed to httpdOutput( ) and ** they will be expanded automatically. */ void index_html(server) httpd *server; { httpdPrintf(server, "Welcome to the httpd server running in process number %d

", getpid()); httpdPrintf(server, "Click here to view a test page

"); httpdPrintf(server, "Click here to authenticate

"); httpdPrintf(server, "Or here for a test wildcard page

"); httpdPrintf(server, "

"); httpdPrintf(server, "Enter your name "); httpdPrintf(server, "

"); return; } void test2_html(server) httpd *server; { httpVar *variable; /* ** Grab the symbol table entry to see if the variable exists */ variable = httpdGetVariableByName(server, "name"); if (variable == NULL) { httpdPrintf(server,"Missing form data!"); return; } /* ** Use httpdOutput() rather than httpdPrintf() so that the variable ** embedded in the text is expanded automatically */ httpdOutput(server,"Hello $name"); } void test3_html(server) httpd *server; { char *path; path = httpdRequestPath(server); httpdOutput(server,"Wilcard dynamic request received

"); httpdPrintf(server,"The requested path was %s

", path); } void login_html(server) httpd *server; { if (httpdAuthenticate(server, "LibHTTPD Test") == 0) return; httpdPrintf(server, "Your username is '%s'

", server->request.authUser); httpdPrintf(server, "Your password is '%s'

", server->request.authPassword); httpdOutput(server, "Click here to force reauthentication"); httpdOutput(server, ". Use a username = test password = 123"); } void login2_html(server) httpd *server; { if (httpdAuthenticate(server, "LibHTTPD Test") == 0) { httpdOutput(server, "Authentication failure(1)."); return; } if (strcmp(server->request.authUser, "test") != 0 || strcmp(server->request.authPassword, "123") != 0) { httpdForceAuthenticate(server, "LibHTTPD Test"); httpdOutput(server, "Authentication failure (2)."); return; } httpdOutput(server, "Your login was accepted."); } void myError404Handler(server, error) httpd *server; int error; { httpdOutput(server,"Whoa there. You hit a page that doesn't exist!



"); httpdOutput(server,"Or in other words : Error 404 "); } int main(argc, argv) int argc; char *argv[]; { httpd *server; char *host; int port, errFlag, result; extern char *optarg; extern int optind, opterr, optopt; int c; struct timeval timeout; host = NULL; port = 80; errFlag = 0; while ( (c=getopt(argc,argv,"h:p:")) != -1 ) { switch ( c ) { case 'h': host=optarg; break; case 'p': port = atoi(optarg); break; default: errFlag++; } } if (errFlag) { fprintf(stderr,"usage: [-h ] [ -p ] "); fprintf(stderr," LibHTTPD version %s ",LIBHTTPD_VERSION); exit(1); } /* ** Ensure that PIPE signals are either handled or ignored. ** If a client connection breaks while the server is using ** it then the application will be sent a SIGPIPE. If you ** don't handle it then it'll terminate your application. */ signal(SIGPIPE, SIG_IGN); /* ** Create a server and setup our logging */ server = httpdCreate(host,port); //创建web服务器 if (server == NULL) { perror("Can't create server"); exit(1); } httpdSetAccessLog(server, stdout); //设置访问日志文件 httpdSetErrorLog(server, stdout); //设置错误日志文件 /* ** We are fussy and don't want the default Error 404 page */ httpdSetErrorFunction(server,404, myError404Handler); //添加404错误回调函数,请求中没有path一般会调用404 /* ** Setup some content for the server */ httpdAddCContent(server,"/", "index.html", HTTP_TRUE, //添加路径的回调函数 NULL, index_html); httpdAddCContent(server,"/", "test2.html", HTTP_FALSE, NULL, test2_html); httpdAddCContent(server,"/", "login.html", HTTP_FALSE, NULL, login_html); httpdAddCContent(server,"/", "login2.html", HTTP_FALSE, NULL, login2_html); httpdAddCWildcardContent(server,"/wildcard", NULL, test3_html); httpdAddStaticContent(server, "/", "test1.html", HTTP_FALSE, NULL, test1_html); httpdAddEmberContect(server,"/","ember.html", HTTP_FALSE, NULL, ember_code); /* ** Go into our service loop */ while(1 == 1) { /* ** Linux modifies the timouet value during the ** select call so we must set it everyt ime. Most ** other UNIX implementations do not modify timeout ** but it doesn't hurt to set it each time anyway */ timeout.tv_sec = 5; timeout.tv_usec = 0; result = httpdGetConnection(server, &timeout); //接收客户端的web请求,请求内容会保存到server变量中 if (result == 0) { printf("Timeout ... "); continue; } if (result < 0) { printf("Error ... "); continue; } if(httpdReadRequest(server) < 0) { httpdEndRequest(server); continue; } httpdProcessRequest(server); //处理客户端的web请求,httpd会根据请求path调用相应的回调函数或者返回相应的file httpdEndRequest(server); } }
     
三、以下libhttpd接口函数的功用,更详细的函数功能参看libhttpd manual: ---------------------------------------------------------------------------------- httpdCreate ( ) 创建WEB服务器 httpd * httpdCreate ( host , port ) char * host int port Example : server = httpdCreate( “192.168.1.1”, HTTP_PORT); if ( server == NULL ) perror ( “Couldn’t create HTTP server” ); server2 = httpdCreate ( NULL , 2048 ); ------------------------------------------------------------------------------------ httpdSetAccessLog( ) 设置访问日志文件 httpdSetAccessLog ( server, fp ) httpd *server; FILE *fp; Example : fp = fopen ( “/tmp/access.log”, “a” ); httpdSetAccessLog ( server, fp ); -------------------------------------------------------------------- httpdSetErrorLog( ) 设置错误日志文件 httpdSetErrorLog ( server, fp ) httpd *server; FILE *fp; Example : httpdSetErrorLog ( server, stderr ); ------------------------------------------------------------------------ httpdSetFileBase( ) 设置文件基本路径名 httpdSetErrorLog ( server, path ) httpd *server; char *path; Example : httpdSetFileBase ( server, “/usr/local/www-pages” ); ------------------------------------------------------------------------ httpdAddCContent( ) 调用C函数产生输出内容 httpdAddCContent ( server, dir, name, indexFlag, preload, functPtr ) httpd *server; char *dir, *name; int indexFlag, (*)( )preload; void (*)( ) functPtr; Example : void index_callbackl ( server ) httpd *server; { httpdOutput(server, “Hello There ”); } httpdAddCContent( server, “/”, “index.html”, HTTP_TRUE, NULL, index_callback); ------------------------------------------------------------------------------------ httpdAddFileContent( ) 将一个外部文件加入到输出内容 httpdAddFileContent ( server, dir, name, indexFlag, preload, path ) httpd *server; char *dir, *name; int indexFlag, (*) ( ) preload; char *path; Example : httpdAddFileContent( server, “/”, “index.html”, HTTP_TRUE, NULL, “/usr/local/www/index.html” ); ----------------------------------------------------------------------------------- httpdAddStaticContent( ) 将一个内部文本BUFFER加入到HTML输出内容 httpdAddStaticContent ( server, dir, name, indexFlag, preload, buf ) httpd *server; char *dir, *name; int indexFlag, (*)( ) preload; char *buf; Example : #define index_content “Hello There ” httpdAddStaticContent( server, “/”, “index.html”, HTTP_TRUE, NULL, index_content ); ------------------------------------------------------------------------------------ httpdAddWildcardContent( ) 增加与通配符匹配的文件内容 httpdAddWildcardContent ( server, dir, preload, path ) httpd *server; char *dir; int (*) ( )preload; char *path; Example : httpdAddWildcardContent(server,“/graphics”, NULL, “/usr/local/www/graphics” ); ----------------------------------------------------------------------------------- httpdAddCWildcardContent( ) 请求指定目录中的任何文件时调用C回调函数 httpdAddCWildcardContent ( server, dir, preload, functPtr ) httpd *server; char *dir; int (*) ( )preload; void (*)( ) functPtr; Example : httpdAddCWildcardContent(server,“/users”, NULL, send_user_info ); --------------------------------------------------------------------------------- httpdGetConnection ( ) 接受一个HTTP连接请求 int httpdGetConnection ( server , timeout) httpd *server; struct timeval *timeout; ----------------------------------------------------------------------- httpdReadRequest ( ) 读取并保存从客户端发送过来的请求和数据 int httpdReadRequest ( server ) httpd *server; ------------------------------------------------------------------------- httpdProcessRequest ( ) 对请求进行处理,并将请求内容发送到客户端浏览器 httpdProcessRequest ( server ) httpd *server; ---------------------------------------------------------------------- httpdEndRequest ( ) 请求结束处理 httpdEndRequest ( server ) httpd *server; ---------------------------------------------------------------------- httpdOutput ( ) 将文本BUFFER内容发送到客户端浏览器 httpdOutput ( server, buffer ) httpd *server; char *buffer Example : httpdOutput ( server, “Hello $name. Welcome to the test server” ); ---------------------------------------------------------------------- httpdPrintf ( ) 按指定格式将内容输出到客户端浏览器 httpdPrintf ( server, format, arg, arg, … ) httpd *server; char *format; Example : httpdPrintf( server, “Hello %s. Welcome to the server running in process number %d”, username, getpid( ) ); ------------------------------------------------------------------------- httpdSetContentType ( ) 设置除HTML文本以外的内容类型 httpdSetContentType( server, type ) httpd *server; char *type Example : httpdSetContentType ( server, “image/jpeg” ); ------------------------------------------------------------------------ httpdSetResponse ( ) 设置返回给客户端浏览器的的响应代码 httpdSetResponse( server, responseInfo ) httpd *server; char *responseInfo; Example : httpdSetResponse ( server, “301 Moved Permanently” ); ------------------------------------------------------------------- httpdAddHeader ( ) 增加HTML头内容 httpdAddHeader( server, header ) httpd *server; char *header; Example : httpdSetResponse ( server, “307 Temporary Redirect” ); httpdAddHeader ( server, “Location: http://www.foo.com/some/new/location”); --------------------------------------------------------------------------------- httpdSendHeaders( ) 发送HTML头 httpdSendHeaders( server) httpd *server; Example : httpdSetContentType ( server, “image/jpeg” ); httpdSendHeaders ( server ); generateJpegData( server ); --------------------------------------------------------------------------------- httpVar * httpdGetVariableByName ( ) 在符号表中查找变量 httpdGetVariableByName( server, varName ) httpd *server; char *varName; Example : varPtr = httpdGetVariableByName ( server, “username” ); if ( varPtr != NULL) uname = varPtr->value ; ------------------------------------------------------------------------------ httpVar * httpdGetVariableByPrefix ( ) 获取第一个与指定前缀相匹配的变量 httpdGetVariableByPrefixe( server, prefix ) httpd *server; char *prefix; ------------------------------------------------------------------------- httpVar * httpdGetNextVariableByPrefix ( ) 获取下一个与指定前缀相匹配的变量 httpdGetNextVariableByPrefixe( varPtr, prefix ) httpVar *varPtr; char *prefix; Example : varPtr = httpdGetVariableByPrefix ( server, “hughes_” ); while ( varPtr != NULL ) { printf(“Name = %s, Value = %s ”, varPtr->name, varPtr->value; varPtr = httpdGetNextVariableByPrefix ( varPtr, “hughes_” ); } ------------------------------------------------------------------------ httpVar * httpdGetVariableByPrefixedName ( ) 在符号表中查找变量 httpdGetVariableByPrefixedName( varPtr, prefix, remainder ) httpVar *varPtr; char *prefix, *remainder; Example : prefixPtr = httpdGetVariableByName ( server, “multi-select-values” ); while ( prefixPtr != NULL ) { prefix = prefixPtr->value; varPtr = httpdGetVariableByPrefixedName(server, prefix, “_username”); printf(“%s_username = %s ”, prefix, varPtr->value; prefixPtr = prefixPtr->nextValue; } ------------------------------------------------------------------------------ httpdAddVariable( ) 在符号表中增加变量 httpdAddVariable( server, name, value ) httpd *server; char *name, *value; Example : httpdAddVariable( server, “background_color”, “#FFFF30” ); httpdOutput( server, “ ”); --------------------------------------------------------------------------- httpdDumpVariables( ) Dump符号表内容 httpdDumpVariables( server ) httpd *server; ------------------------------------------------------------------------- httpdSet( ) 设置 httpdSet( server, name, value ) httpd *server; char *name, *value; --------------------------------------------------------------------------- httpdAuthenticate( ) 使用用户名和口令进行身份认证 httpdAuthenticate( server, realm ) httpd *server; char *realm; --------------------------------------------------------------------------- httpdForceAuthenticate( ) 强迫身份认证 httpdForceAuthenticate( server, realm ) httpd *server; char *realm; ------------------------------------------------------------------------------ httpdAddAcl( ) 在ACL表中增加访问控制项 httpdAddAcl( server, acl, cidrAddr, action ) httpd *server; httpAcl *acl; char *cidrAddr; int action ----------------------------------------------------------------------------- httpdSetDefaultAcl( ) 设置默认ACL httpdSetDefaultAcl( server, acl ) httpd *server; httpAcl *acl; -------------------------------------------------------------------- httpdCheckAcl( ) 进行ACL检查 httpdCheckAcl( server, acl ) httpd *server; httpAcl *acl; ------------------------------------------------------------------- httpdUrlEncode( ) 进行URL解码 char * httpdUrlEncode( buf ) char *buf; ------------------------------------------------------------------- httpdRequestMethod( ) 获取访问方式(HTTP_GET/HTTP_POST) int httpdRequestMethod( server ) httpd *server; -------------------------------------------------------------------- httpdRequestMethodName( ) 获取访问方式名字 char *httpdRequestMethodName( server ) httpd *server; ------------------------------------------------------------------ httpdRequestPath( ) 获取URL请求路径 char *httpdRequestPath( server ) httpd *server; ---------------------------------------------------------------------- httpdRequestContentType( ) 获取当前请求内容类型 char *httpdRequestContentType( server ) httpd *server; ----------------------------------------------------------------------- httpdRequestContentLength( ) 获取当前请求发送的内容长度 int httpdRequestContentLength( server ) httpd *server; -----------------------------------------------------------------------