Example of the use method for the libevent library

  • 2020-04-02 02:04:43
  • OfStack

Then write a very simple Time Server example: when you connect to the Server end directly provides the Time, and then ends the connection. Event_init () represents the variable used to initialize the libevent. Event_set (&ev, s, EV_READ | EV_PERSIST, connection_accept, &ev) puts the s File Description into ev (the first parameter and the second parameter) and tells it to call connection_accept() (the fourth parameter) when the event (EV_READ of the third parameter) occurs, dropping ev as an argument (the fifth parameter). The EV_PERSIST message says do not remove the event when the call goes in (keep it in the event Queue), which can be compared to the code that registers connection_time() inside connection_accept(). Event_add (&ev, NULL) registers the ev in the event queue, and the second parameter specifies a Timeout time, which is set to NULL to ignore.
Note: this code comes from the network and is crude, but the usage of libevent is clear.
Attached to the source code:


#include <netinet/in.h>   
#include <sys/socket.h>   
#include <sys/types.h>   
#include <event.h>   
#include <stdio.h>   
#include <time.h>   
void connection_time(int fd, short event, struct event *arg)   
{   
    char buf[32];   
    struct tm t;   
    time_t now;   
    time(&now);   
    localtime_r(&now, &t);   
    asctime_r(&t, buf);   
    write(fd, buf, strlen(buf));   
    shutdown(fd, SHUT_RDWR);   
    free(arg);   
}   
void connection_accept(int fd, short event, void *arg)   
{   
     
    fprintf(stderr, "%s(): fd = %d, event = %d.n", __func__, fd, event);   
     
    struct sockaddr_in s_in;   
    socklen_t len = sizeof(s_in);   
    int ns = accept(fd, (struct sockaddr *) &s_in, &len);   
    if (ns < 0) {   
        perror("accept");   
        return;   
    }   
     
    struct event *ev = malloc(sizeof(struct event));   
    event_set(ev, ns, EV_WRITE, (void *) connection_time, ev);   
    event_add(ev, NULL);   
}   
int main(void)   
{   
     
    int s = socket(PF_INET, SOCK_STREAM, 0);   
    if (s < 0) {   
        perror("socket");   
        exit(1);   
    }   
     
    struct sockaddr_in s_in;   
    bzero(&s_in, sizeof(s_in));   
    s_in.sin_family = AF_INET;   
    s_in.sin_port = htons(7000);   
    s_in.sin_addr.s_addr = INADDR_ANY;   
    if (bind(s, (struct sockaddr *) &s_in, sizeof(s_in)) < 0) {   
        perror("bind");   
        exit(1);   
    }   
     
    if (listen(s, 5) < 0) {   
        perror("listen");   
        exit(1);   
    }   
     
    event_init();   
     
    struct event ev;   
    event_set(&ev, s, EV_READ | EV_PERSIST, connection_accept, &ev);   
     
    event_add(&ev, NULL);   
    event_dispatch();   
    return 0;   
}

Writing a Nonblocking Network Program usually deals with Buffering, but it's not easy to write, mainly because read() or recv() doesn't guarantee you can read a line at a time.
A fairly good Buffer Library can be used in libevent. The full description can be seen in man event. The most commonly used functions are evbuffer_add() and evbuffer_readline().
The following directly provides libevent-buff. C as an example, after the compilation to see the execution results, then look back to the source code should have a feeling:


#include <sys/time.h>   
#include <event.h>   
#include <stdio.h>   
void printbuf(struct evbuffer *evbuf)   
{   
    for (;;) {   
        char *buf = evbuffer_readline(evbuf);   
        printf("* buf = %p, the string = "e[1;33m%se[m"n", buf, buf);   
        if (buf == NULL)   
            break;   
        free(buf);   
    }   
}   
int main(void)   
{   
    struct evbuffer *evbuf;   
    evbuf = evbuffer_new();   
    if (evbuf == NULL) {   
        fprintf(stderr, "%s(): evbuffer_new() failed.n", __func__);   
        exit(1);   
    }   
     
    u_char *buf1 = "gslin";   
    printf("* Add "e[1;33m%se[m".n", buf1);   
    evbuffer_add(evbuf, buf1, strlen(buf1));   
    printbuf(evbuf);   
    u_char *buf2 = " is reading.nAnd he is at home.nLast.";   
    printf("* Add "e[1;33m%se[m".n", buf2);   
    evbuffer_add(evbuf, buf2, strlen(buf2));   
    printbuf(evbuf);   
    evbuffer_free(evbuf);   
}   

The last event_dispatch() indicates an event loop, which is executed as a callback function when an event occurs on any of the File Description in the Queue.


Related articles: