Question

I am newbie in libevent and socket programming that's why I have question about how libevent working as asynchronous and non blocking. Here is the reference code. https://github.com/libevent/libevent/blob/master/sample/http-server.c

static void dump_request_cb(struct evhttp_request *req, void *arg)
{
    const char *cmdtype;
    struct evkeyvalq *headers;
    struct evkeyval *header;
    struct evbuffer *buf;

    printf("Request Start\n");
    sleep(30); // delay to read request to check non blocking event.

    switch (evhttp_request_get_command(req)) {
    case EVHTTP_REQ_GET: cmdtype = "GET"; break;
    case EVHTTP_REQ_POST: cmdtype = "POST"; break;
    case EVHTTP_REQ_HEAD: cmdtype = "HEAD"; break;
    case EVHTTP_REQ_PUT: cmdtype = "PUT"; break;
    case EVHTTP_REQ_DELETE: cmdtype = "DELETE"; break;
    case EVHTTP_REQ_OPTIONS: cmdtype = "OPTIONS"; break;
    case EVHTTP_REQ_TRACE: cmdtype = "TRACE"; break;
    case EVHTTP_REQ_CONNECT: cmdtype = "CONNECT"; break;
    case EVHTTP_REQ_PATCH: cmdtype = "PATCH"; break;
    default: cmdtype = "unknown"; break;
    }

    printf("Received a %s request for %s\nHeaders:\n",
        cmdtype, evhttp_request_get_uri(req));

    headers = evhttp_request_get_input_headers(req);

    for (header = headers->tqh_first; header;
       header = header->next.tqe_next) {
            printf("  %s: %s\n", header->key, header->value);
    }
    buf = evhttp_request_get_input_buffer(req);

    puts("Input data: <<<");

    while (evbuffer_get_length(buf)) {
            int n;
            char cbuf[128];
            n = evbuffer_remove(buf, cbuf, sizeof(cbuf));
            if (n > 0)
                    (void) fwrite(cbuf, 1, n, stdout);
    }
    puts(">>>");

    evhttp_send_reply(req, 200, "OK", NULL);
}

I creating delay of 30 secs in above request.

When I send two request from browser. The code should immediately start serving two request at a time. but this is not happened. The real scenario is that second request serve after completion of first request with 30 secs delay. it means it takes total of 60 secs to served two requests.

So could anyone tell me how it works as non_blocking.

Was it helpful?

Solution

The sleep(30) call you made, is blocking, libevent doesn't do any black magic to prevent you from performing blocking calls.
You need to be careful and use only non-blocking APIs. In this case you want to delay response for 30 seconds, so easy enough you can use libevent's evtimer_add() . But this same principle applies to any kind of api you want to use, you must use them in non blocking way (file reads, calls to other servers, DB access, etc).

OTHER TIPS

Thanks For your kind suggestions.

I did non-blocking socket by using threads concept and parallelize the events following way.

void *newThread(void *arg){
printf("Before thread start\n");
struct evhttp_request *req;
req = (struct evhttp_request *)arg;
sleep(30);
evhttp_send_reply(req, 200, "OK", NULL);
printf("After thread end\n");
}

static void dump_request_cb(struct evhttp_request *req, void *arg)
{
const char *cmdtype;
struct evkeyvalq *headers;
struct evkeyval *header;
struct evbuffer *buf;

printf("Request Start\n");
sleep(30); // delay to read request to check non blocking event.

switch (evhttp_request_get_command(req)) {
case EVHTTP_REQ_GET: cmdtype = "GET"; break;
case EVHTTP_REQ_POST: cmdtype = "POST"; break;
case EVHTTP_REQ_HEAD: cmdtype = "HEAD"; break;
case EVHTTP_REQ_PUT: cmdtype = "PUT"; break;
case EVHTTP_REQ_DELETE: cmdtype = "DELETE"; break;
case EVHTTP_REQ_OPTIONS: cmdtype = "OPTIONS"; break;
case EVHTTP_REQ_TRACE: cmdtype = "TRACE"; break;
case EVHTTP_REQ_CONNECT: cmdtype = "CONNECT"; break;
case EVHTTP_REQ_PATCH: cmdtype = "PATCH"; break;
default: cmdtype = "unknown"; break;
}

printf("Received a %s request for %s\nHeaders:\n",
    cmdtype, evhttp_request_get_uri(req));

headers = evhttp_request_get_input_headers(req);

for (header = headers->tqh_first; header;
   header = header->next.tqe_next) {
        printf("  %s: %s\n", header->key, header->value);
}
buf = evhttp_request_get_input_buffer(req);

puts("Input data: <<<");

while (evbuffer_get_length(buf)) {
        int n;
        char cbuf[128];
        n = evbuffer_remove(buf, cbuf, sizeof(cbuf));
        if (n > 0)
                (void) fwrite(cbuf, 1, n, stdout);
}
puts(">>>");
}

In this way even though a sleep delay was there, every request from the clients gets parallel with the previous ones. I could not find any solution in the libevent module and completed my task with an alternative threading concept.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top