libwebsockets(二)实现简易http服务器

根据官方的说明来看,从2.0版本起,http协议的服务器已经自动集成在库中,不需要我们自己去实现。下面介绍如何使用库去实现http服务器。

1、填充服务器创建需要的参数

lws_context_creation_info是创建服务器句柄时用来定制服务器信息的结构体,所以我们首先需要填充该结构体。该结构体的定义如下。

/*这里只列出我们常用的成员,注释很详细,不做过多解释*/
struct lws_context_creation_info {
    int port;
    /**< VHOST: Port to listen on. Use CONTEXT_PORT_NO_LISTEN to suppress
     * listening for a client. Use CONTEXT_PORT_NO_LISTEN_SERVER if you are
     * writing a server but you are using \ref sock-adopt instead of the
     * built-in listener */
    const char *iface;
    /**< VHOST: NULL to bind the listen socket to all interfaces, or the
     * interface name, eg, "eth2"
     * If options specifies LWS_SERVER_OPTION_UNIX_SOCK, this member is
     * the pathname of a UNIX domain socket. you can use the UNIX domain
     * sockets in abstract namespace, by prepending an at symbol to the
     * socket name. */
    const struct lws_protocols *protocols;
    /**< VHOST: Array of structures listing supported protocols and a protocol-
     * specific callback for each one.  The list is ended with an
     * entry that has a NULL callback pointer. */
    const struct lws_extension *extensions;
    /**< VHOST: NULL or array of lws_extension structs listing the
     * extensions this context supports. */
    const char *log_filepath;
    /**< VHOST: filepath to append logs to... this is opened before
     *      any dropping of initial privileges */
    const struct lws_http_mount *mounts;
    /**< VHOST: optional linked list of mounts for this vhost */

        ...
};

protocols用来指明该服务器可以处理的协议类型,以数组的形式提供并NULL作为数组结尾,如果不指定则默认使用http协议。

mounts用来设置与http服务器相关的参数,比如主机路径、URL路径、默认的主页文件等等。我们在这里初始化如下:

    static const struct lws_http_mount mount = {
        /* .mount_next */               NULL,           /* linked-list "next" */
        /* .mountpoint */               "/",            /* mountpoint URL */
        /* .origin */                   ".",            /* serve from dir */
        /* .def */                      "index.html",   /* default filename */
        /* .protocol */                 NULL,
        /* .cgienv */                   NULL,
        /* .extra_mimetypes */          NULL,
        /* .interpret */                NULL,
        /* .cgi_timeout */              0,
        /* .cache_max_age */            0,
        /* .auth_mask */                0,
        /* .cache_reusable */           0,
        /* .cache_revalidate */         0,
        /* .cache_intermediaries */     0,
        /* .origin_protocol */          LWSMPRO_FILE,   /* files in a dir */
        /* .mountpoint_len */           1,              /* char count */
        /* .basic_auth_login_file */    NULL,
    };

    struct lws_context_creation_info info;

    /*初始化内存*/
    memset(&info, 0, sizeof info);
    info.port = 7681;
    info.mounts = &mount;

2、创建服务器句柄

调用的函数为

LWS_VISIBLE LWS_EXTERN struct lws_context* lws_create_context(struct lws_context_creation_info *info)   

当创建失败时,将会返回NULL

    struct lws_context *context;
    context = lws_create_context(&info);

3、运行服务器

共有4个函数可以执行运行服务器,具体的介绍可以参见 api,这里我们使用第1个函数。


/*
 * context: 服务器句柄;
 * timeout_ms: 等待超时时间,即没有找到需要处理的连接需要等待的时间,为0则立即返回;
 * pollfd: poll结构;
 * tsi: 线程索引,默认为0;
 */

int lws_service (struct lws_context *context, int timeout_ms)
int lws_service_fd (struct lws_context *context, struct lws_pollfd *pollfd)
int lws_service_fd_tsi (struct lws_context *context, struct lws_pollfd *pollfd, int tsi)
int lws_service_tsi (struct lws_context *context, int timeout_ms, int tsi)      

直接调用lws_service即可。

    /*设置超时时间为1000ms*/
    lws_service(context, 1000);

4、整体代码

/*
 * lws-minimal-http-server
 *
 * Copyright (C) 2018 Andy Green 
 *
 * This file is made available under the Creative Commons CC0 1.0
 * Universal Public Domain Dedication.
 *
 * This demonstrates the most minimal http server you can make with lws.
 *
 * To keep it simple, it serves stuff in the directory it was started in.
 * You can change that by changing mount.origin
 */

#include 
#include 
#include 

static int interrupted;

static const struct lws_http_mount mount = {
    /* .mount_next */       NULL,       /* linked-list "next" */
    /* .mountpoint */       "/",        /* mountpoint URL */
    /* .origin */           ".",        /* serve from dir */
    /* .def */          "index.html",   /* default filename */
    /* .protocol */         NULL,
    /* .cgienv */           NULL,
    /* .extra_mimetypes */      NULL,
    /* .interpret */        NULL,
    /* .cgi_timeout */      0,
    /* .cache_max_age */        0,
    /* .auth_mask */        0,
    /* .cache_reusable */       0,
    /* .cache_revalidate */     0,
    /* .cache_intermediaries */ 0,
    /* .origin_protocol */      LWSMPRO_FILE,   /* files in a dir */
    /* .mountpoint_len */       1,      /* char count */
    /* .basic_auth_login_file */    NULL,
};

void sigint_handler(int sig)
{
    interrupted = 1;
}

int main(int argc, char **argv)
{
    struct lws_context_creation_info info;
    struct lws_context *context;
    int n = 0;

    signal(SIGINT, sigint_handler);

    memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
    info.port = 7681;
    info.mounts = &mount;

    lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER
            /* | LLL_INFO */ /* | LLL_DEBUG */, NULL);

    lwsl_user("LWS minimal http server | visit http://localhost:7681\n");

    context = lws_create_context(&info);
    if (!context) {
        lwsl_err("lws init failed\n");
        return 1;
    }

    while (n >= 0 && !interrupted)
        n = lws_service(context, 1000);

    lws_context_destroy(context);

    return 0;
}

你可能感兴趣的:(websockets)