libhttpd深入分析

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/下的用户手册。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值