Libevent Source Code Analysis

Source: Internet
Author: User
Tags doxygen epoll

The 1.Libevent has several notable highlights
Libevent encapsulates the most efficient network model at the bottom, the Epoll model under Windows Compio,linux, the Kqueue of FreeBSD, provides a unified asynchronous calling interface; The framework is used by chrome,memcached, which is driven by events. Libevent also supports dns,http protocol and RPC call framework. Libevent always chooses the optimal multiplexing technology (Epoll ...) in the corresponding system framework. Implement the Libevent framework.
* Event-driven (Event-driven), high performance;
* Lightweight, focus on the network, rather than ACE so bloated and huge;
* Cross-platform, support Windows, Linux, *bsd and Mac Os;
* Speed: Libevent attempts to use the highest speed non-blocking IO implementations on each platform without introducing too much extra overhead.
* Support multiple I/O multiplexing technology, Epoll, poll, Dev/poll, select and Kqueue, etc.
* Supports events such as I/O, timers and signals;
* Register event priority;
* Unified management of non-blocking files, timers and signal events
2.libevent implements the reactor mode

The most important idea of reactor mode is: Block + event + multi-channel distribution, event-driven, synchronous non-blocking. Currently, Libevent supports high-concurrency network programming models such as/dev/poll,kqueue (2), select (2), poll (2), and Epoll (4).
Reactor mode is one of the prerequisites for writing high-performance Web servers, and it has the following advantages:
1) Fast response, will not be blocked by a single synchronization time, although the reactor itself is still synchronous (for the activation event processing also requires a processing, not using multithreading technology);
2) programming is relatively simple, can avoid complex multi-threaded and synchronization problems, and avoid multi-threaded/process switching overhead;
3) scalability, you can easily increase the number of reactor instances to make full use of CPU resources (can create multiple non-interfering reactors, to manage different file handles);
4) reusability, the reactor framework itself is independent of the specific event handling logic and has high reusability;
Reactor model, the necessary 4 components: Event source, reactor framework, multiplexing mechanism, and event handlers.
Multiplexing corresponds to Libevent, which is still select, poll, Epoll, etc., but Libevent uses the structure eventop to encapsulate, with a unified interface to support these I/O multiplexing mechanism, achieve the purpose of hiding the underlying system mechanism.
3.libevent method functions are not thread-safe, because most of them operate non-mutex (locking) processing of the queue or list (signal waiting queue, file and timer waiting queue, ready queue, etc.) resources, so when using multi-threading for libevent, some techniques are needed. such as the message notification mechanism (queue + pipeline)
4.libevent Part interface function
Each program that uses libevent needs to include the <event.h> header file, and it needs to pass the-LEVENT flag to the connector linker.
(1) the Event_init () or event_base_new () function performs an initialization of the Libevent library once, constructing a libevent instance.
(2) Event notification: For each file descriptor you want to monitor, you must declare an event structure and call Event_set () to initialize the members of the struct (such as the callback function that sets the event). To activate the notification, you need to add the structure to the Libevent instance monitoring event list by calling Event_add (). As long as the event is alive, it is necessary to maintain the allocated event structure, so the event structure needs to be applied on the heap (heap). Finally, you need to call the Event_dispatch () function to loop and dispatch events.
(3) I/O buffers: To implement a more efficient IOCP method under Windows, API,IOCP will not notify your program to copy data immediately when it is ready for read and write events, but only notify the application when the data has been copied from the kernel state to the user state. Libevent 2 provides a bufferevent interface to support this programming paradigm. As follows: Libevent provides an abstraction of the top level of a recurring callback event. This abstraction is known as a buffered event (buffered). Buffered events provide input and output buffers that are automatically populated and streamed out (drained). Buffer time users no longer need to directly manipulate I/O, but only read from the input buffer, write to the output buffer. Once initialized with Bufferevent_new (), the bufferevent structure can be reused through bufferevent_enable () and bufferevent_disable (). As an alternative, read and write to a set of interfaces needs to be done by calling the Bufferevent_read () and Bufferevent_write () functions. When bufferevent is activated due to a read event, the subsequent callback read function will automatically read the data from the file descriptor. The write function will be called back whenever the output buffer space is exhausted to less than the Write water level (low watemark), which typically defaults to 0.
(4) Timer: Libevent by creating a timer to participate in a callback event after a certain timeout period. The Evtimer_set () function will prepare (allocate) an event structure to be used as a timer. In order to activate the timer, you need to call the Evtimer_add () function (the file descriptor calls the Event_add function). Instead, you need to call the Evtimer_del () function.
(5) Timeout: In addition to a simple timer, libevent can specify a timeout event for the file descriptor that triggers a file descriptor that is not activated after a period of time to perform the appropriate action. The Timeout_set () function can initialize an event structure for a time-out. Once initialized successfully, the event must be activated through the Timeout_add () function. In order to cancel a timeout event, you can call the Timeout_del () function.
(6) Asynchronous DNS resolution: Libevent provides an asynchronous DNS resolver that can be used in place of a standard DNS resolver. These functions can be imported by including the <evdns.h> header file in the program. Before you use any parser function, you must call the Evdns_init () function to initialize the library of functions. To convert a domain name to an IP address, you can call the Evdns_resolve_ipv4 () function. In order to execute a reverse query, you can call the Evdns_resolve_reverse () function. All of these functions, when found, use a callback method to avoid the occurrence of blocking.
(7) Event-driven HTTP server: A simple HTTP client/server implementation. Libevent provides a simple event-driven HTTP server that can be embedded in your program and can handle HTTP requests. In order to use this ability, you should include the <evhttp.h> header file in your program. You can create a server by calling the Evhttp_new () function. Add an address and port for listening by using the Evhttp_bind_socket () function. You can then register one or more handle handles to incoming requests. For each URI, you can specify a callback through the EVHTTP_SET_CB () function. Usually, a callback function can also be registered through the EVHTTP_SET_GENCB () function, and if no other callback has been registered to get the URI, then the callback will be associated with it.
(8) RPC Server and client framework: Libevent provides a programming framework for creating RPC servers and clients. It will host the data structure of all the marshalling and reconciliation groups.
(9) API Reference: To browse the full Libevent API documentation, click on the link below.
http://www.wangafu.net/~nickm/libevent-1.4/doxygen/html/event_8h.html, event.h libevent main header file
Http://www.wangafu.net/~nickm/libevent-1.4/doxygen/html/evdns_8h.html-evdns.h Asynchronous DNS Resolver
Http://www.wangafu.net/~nickm/libevent-1.4/doxygen/html/evhttp_8h.html-Evhttp.h built-in Libevent-based HTTP server
Http://www.wangafu.net/~nickm/libevent-1.4/doxygen/html/evrpc_8h.html-Evrpc.h creating a programming framework for RPC servers and clients
struct event_base *event_base_new (void);The function is assigned and returns a new Event_base (libevent instance, Event Manager instance) with default settings. The function detects the environment variable and returns a pointer to Event_base. If an error occurs, NULL is returned.
struct event_base *event_init (void);An older version of the generated Event manager instance
void Event_set (struct event *ev, int fd, short evtype, Void (*CB) (Int. FD, short evtype, void * arg), void *arg)Initializes an event (a file event or timer event) that indicates what event the event is specific to. That is, set the file handle, event type, and callback function for event management.
EV: Executes the event object to initialize; FD: The handle of the event binding, which is the signal of interest for the signal event; Evtype: The type of event that is concerned on the FD, it can be ev_read, Ev_write, ev_signal; CB: This is a function pointer, because the timing event does not require FD, and the timing event is set according to the time-out value of Add (Event_add), so there is no need to set this event. Event Manager can manage 3 types of events: Entype: (1) I/O events: Ev_write and Ev_read fd= file descriptor (2) Timed events: Ev_timeout fd=-1 (3) signal: ev_signal fd= Signal Number (4) Auxiliary options: Ev_persist, which indicates a permanent event that is not taken away from the waiting queue, is permanently registered, or is only monitored once. entype=ev_read| Ev_persist
The event Manager can assume that there are 3 queues: A signal waiting queue, a file and a timer waiting queue, and a ready queue.
void Evtimer_set (struct event *ev, void (*CB) (int, short, void *), null,void *arg);Can only be used to initialize a timer event.
Evtimer_set (&ev, TIMER_CB, null); <=>event_set (&ev,-1, 0, TIMER_CB, null);1 means that this is a timer event, not a file handle. The Evtimer_set and Event_set functions are actually assigned values to the event structure.
void Event_base_set (struct event_base* base, struct event *ev); Specifies which Event manager this event EV is managed by.
void Event_add (struct event *ev, struct timeval *timeout);Event waiting Queue (registration) that adds events to the EV Event Manager, where timeout is a timed value and only the timer event is required;
void Event_base_dispatch (struct event_base *base);The event manager loops, starts monitoring the events in the wait queue, takes the event out of the waiting queue, puts it in the Ready event queue, and then prioritizes it (if you want to re-monitor the event, you need to use Event_add to add the event to the Wait event queue again)

5. Basic steps used by the event manager
(1) Create an event manager;
(2) Create an event and assign a value to the event using Event_set, specifying the event type callback function;
(3) Specify an event manager for the event, and if not specified, the default is the current manager pointed to by the present pointer;
(4) Adding events to the manager event waiting queue;
(5) Run the manager event loop.

6. Example
(1) Timer
#include <stdio.h>
#include <event.h>
void onTime (int sock,short event,void *arg)
{
printf ("Game over!\n");
struct Timeval TV;
Tv.tv_sec = 1;
tv.tv_usec = 0;
After the event is executed, it is deleted by default and needs to be re-add to repeat the execution
Event_add (struct event*) ARG,&AMP;TV);
}
int main ()
{
Event_init (); Initializes a libevent instance (the event manager), and the pointer is placed in the underlying current instance.
struct event evtime; Defining a Timer Event
Evtimer_set (&evtime,ontime,&evtime); Set Timer callback function
struct Timeval TV; 1s after execution
Tv.tv_sec = 1;
tv.tv_usec = 0;
Event_add (&AMP;EVTIME,&AMP;TV); Add Event
Event_dispatch (); Cyclic distribution of events
return 0;
}
Compilation: Gcc-o time_test time_test.c-i/usr/local/libevent/include-l/usr/local/libevent/lib-levent

(2) TCP Server
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <event.h>
struct Event_base *base;
Read Events
void OnRead (int clifd,short ievent,void *arg)
{
int Ilen;
Char buf[1500];
Ilen = recv (clifd,buf,1500,0);
if (ilen <= 0)
{
printf ("Client close\n");
struct Event *pread = (struct event*) arg;
Event_del (Pread);
Delete pread;
Close (CLIFD);
Return
}
Buf[ilen] = ' + ';
printf ("Accpet:%s\n", buf);
}
Connection Events
void onaccept (int svrfd,short ievent,void *arg)
{
int clifd;
struct sockaddr_in cliaddr;

socklen_t sinsize = sizeof (CLIADDR);
CLIFD = Accept (SVRFD, (struct sockaddr*) &cliaddr,&sinsize);

struct Event *pread = new event;
Event_set (pread,clifd,ev_read|  Ev_persist,onread,pread); Registering read (write) events
Event_base_set (Base,pread);
Event_add (Pread,null);
}
int main ()
{
int svrfd;
struct sockaddr_in svraddr;

memset (&svrfd,0,sizeof (SVRADDR));
svraddr.sin_family = af_inet;
Svraddr.sin_port = htons (1234);
SVRADDR.SIN_ADDR.S_ADDR = inet_addr ("127.0.0.1");
SVRFD = socket (af_inet,sock_stream,0);
Bind (SVRFD, (struct sockaddr*) &svraddr,sizeof (SVRADDR));
Listen (svrfd,10);
Initializing the event Library
Base = Event_base_new ();
Initializes a connection event, Ev_presist specifies that the event is repeatedly executed
struct event evlisten;
Event_set (&evlisten,svrfd,ev_read| Ev_persist,onaccept,null);
Set as base event
Event_base_set (Base,&evlisten);
Add Event
Event_add (&evlisten,null);
Event Loops
Event_base_dispatch (base);
return 0;
}
To implement a more efficient IOCP method under Windows, the API,IOCP will not notify your program to copy data when it is ready for read and write events, but only notify the application when the data has been copied from the kernel state to the user state. Libevent 2 provides a bufferevent interface to support this programming paradigm.


(3) HTTP Server
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <event.h>
#include <evhttp.h>
void Reqhandler (struct evhttp_request *req,void *arg)
{
struct Evbuffer *buf = evbuffer_new ();
evbuffer_add_printf (buf, "Thanks for the Request"); Send response
Evhttp_send_reply (REQ,HTTP_OK, "Client", buf);
Evbuffer_free (BUF);
Return
}
int main (int argc,char **argv)
{
Short port = 8000;
const char *ADDR = "192.168.1.11";
struct Evhttp *httpserv = NULL;
Event_init ();
Httpserv = Evhttp_start (Addr,port); Start the HTTP service
EVHTTP_SET_GENCB (Httpserv, reqhandler,null); Set callback
printf ("Server started on port%d\n", port);
Event_dispatch ();
return 0;
}


This article from "Tech record" blog, declined reprint!

Libevent Source Code Analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.