libhttpd是一个小型的嵌入式web server,在开发过程中,如果需要web server,但仅仅需要实现固定两三个web网页服务及处理小部分http请求,则可以将Libhttpd嵌入开发中,生成动态库文件使用。
libhttp:http://www.hughes.com.au/products/libhttpd/
libhttpd提供了良好的API,可以实现web server的静态和动态内容处理。
创建web server,需要使用httpdCreate() 来实现,创建成功后,httpd操作将通过libhttpd的API library进行交互。
在API library中,可以使用httpSetAccessLog() 和httpdsetErrorLog() 来产生服务log。
libhttpd服务定义了特定的web服务内容:
- 静态内容:HTML静态数据
- 文件内容:定义一个外部文件
- 目录内容:定义特定的服务路径和目录
- 动态内容:通过c函数产生特定的动态内容输出
一旦内容被定义好,则进入web server的操作循环中,通过以下函数处理http request:
- httpdGetConnection():接收一个http连接
- httpdReadRequest():读取和处理http request
- httpdProcessRequest():对http请求产生输出
- httpdEndRequest():断开http会话,清空
使用libhttpd的API,需要在应用程序源码中加入include文件——htttpd.h,并将这个头文件默认安装于/usr/local/include中。如果需要连接安装于/usr/local/lib中的libhttpd.a,则需要加入下面的连接:
-L /usr/local/lib -lhttpd
查看代码:
httpdCreate()通过主机名和端口号创建web server:
httpd *httpdCreate(host, port)
char *host;
int port;
{
httpd *new;
int sock,
opt;
struct sockaddr_in addr;
/*
** Create the handle and setup it's basic config
*/
new = malloc(sizeof(httpd));
if (new == NULL)
return(NULL);
bzero(new, sizeof(httpd));
new->port = port;
if (host == HTTP_ANY_ADDR)
new->host = HTTP_ANY_ADDR;
else
new->host = strdup(host);
new->content = (httpDir*)malloc(sizeof(httpDir));
bzero(new->content,sizeof(httpDir));
new->content->name = strdup("");
/*
** Setup the socket
*/
#ifdef _WIN32
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
/* Found a usable winsock dll? */
if( err != 0 )
return NULL;
/*
** Confirm that the WinSock DLL supports 2.2.
** Note that if the DLL supports versions greater
** than 2.2 in addition to 2.2, it will still return
** 2.2 in wVersion since that is the version we
** requested.
*/
if( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
/*
** Tell the user that we could not find a usable
** WinSock DLL.
*/
WSACleanup( );
return NULL;
}
/* The WinSock DLL is acceptable. Proceed. */
}
#endif
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
free(new);
return(NULL);
}
# ifdef SO_REUSEADDR
opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&opt,sizeof(int));
# endif
new->serverSock = sock;
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
if (new->host == HTTP_ANY_ADDR)
{
addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
else
{
addr.sin_addr.s_addr = inet_addr(new->host);
}
addr.sin_port = htons((u_short)new->port);
if (bind(sock,(struct sockaddr *)&addr,sizeof(addr)) <0)
{
close(sock);
free(new);
return(NULL);
}
listen(sock, 128);
new->startTime = time(NULL);
return(new);
}
httpdDestroy()销毁web server服务:
void httpdDestroy(server)
httpd *server;
{
if (server == NULL)
return;
if (server->host)
free(server->host);
free(server);
}
httpdAddCContent()函数增加反馈给客户端的web内容:
int httpdAddCContent(server, dir, name, indexFlag, preload, function)
httpd *server;
char *dir;
char *name;
int (*preload)();
void (*function)();
{
httpDir *dirPtr;
httpContent *newEntry;
dirPtr = _httpd_findContentDir(server, dir, HTTP_TRUE);
newEntry = malloc(sizeof(httpContent));
if (newEntry == NULL)
return(-1);
bzero(newEntry,sizeof(httpContent));
newEntry->name = strdup(name);
newEntry->type = HTTP_C_FUNCT;
newEntry->indexFlag = indexFlag;
newEntry->function = function;
newEntry->preload = preload;
newEntry->next = dirPtr->entries;
dirPtr->entries = newEntry;
return(0);
}
通过functon这个函数指针,导入应用函数,
可以通过dir/name来访问定义好的web内容:
实例:
void index_callbackl ( server )
httpd *server;
{
httpdOutput(server, “<HTML><BODY>Hello There</BODY></HTML>\n”);
}
httpdAddCContent( server, “/”, “index.html”, HTTP_TRUE, NULL, index_callback);
httpdAddFileContent()函数,可以将静态的html页面加入的web server中。
int httpdAddFileContent(server, dir, name, indexFlag, preload, path)
httpd *server;
char *dir,
*name;
int (*preload)();
int indexFlag;
char *path;
{
httpDir *dirPtr;
httpContent *newEntry;
dirPtr = _httpd_findContentDir(server, dir, HTTP_TRUE);
newEntry = malloc(sizeof(httpContent));
if (newEntry == NULL)
return(-1);
bzero(newEntry,sizeof(httpContent));
newEntry->name = strdup(name);
newEntry->type = HTTP_FILE;
newEntry->indexFlag = indexFlag;
newEntry->preload = preload;
newEntry->next = dirPtr->entries;
dirPtr->entries = newEntry;
if (*path == '/')
{
/* Absolute path */
newEntry->path = strdup(path);
}
else
{
/* Path relative to base path */
newEntry->path = malloc(strlen(server->fileBasePath) +
strlen(path) + 2);
snprintf(newEntry->path, HTTP_MAX_URL, "%s/%s",
server->fileBasePath, path);
}
return(0);
}
实例,增加一个index.html文件:
httpdAddFileContent( server, “/”, “index.html”, HTTP_TRUE, NULL, “/www/index.html” );
httpdAddStaticContent()函数,加入静态的web内容。
实例:
#define index_content “<HTML><BODY>Hello There</BODY></HTML>\n”
httpdAddStaticContent( server, “/”, “index.html”, HTTP_TRUE, NULL, index_content );
httpdAddWildcardContent()函数,加入html页面包含的文件,例如图片 ,html pages等
实例:
httpdAddWildcardContent(server,“/graphics”, NULL, “/usr/local/www/graphics” );
httpdAddCWildcardContent()函数,通过一个c函数callback,执行特定的web请求内容的修改。
实例:
httpdAddCWildcardContent(server,“/users”, NULL, send_user_info );
libhttpd在与客户端进行交互操作,执行以下操作:
- 接收从客户端的browser发来的TCP/IP连接
- 解析客户端发送来的http request
- 处理http request反馈给客户段请求数据
- 清空并终止连接
以上执行动作通过下面的函数实现
- httpdGetConnection()
- httpdReadRequest()
- httpdProcessRequest()
- httpdEndRequest()
libhttpd回应客户端的http request并反馈数据内容,通过以下函数实现:
- httpdOutput()
- httpdPrintf()
- httpdSetContentType() 设置了html中包含的链接文件
- httpdSetResponse() 响应http请求是反馈的请求结果设置
- httpAddHeader() 增加反馈给客户端的http headers
- httpdSendHeaders() 为动态内容设定http header
libhttpd还增加有form data,cookies,symbol tables等web内容的处理函数,具体内容查看libhttpd源码以及源码中doc/下的用户手册。

6641

被折叠的 条评论
为什么被折叠?



