Libevent安裝與使用(一)

What the lowest level of the Libevent API does:
  Provides a consistent interface to various select() replacements, using the most efficient version available on the computer where it’s running.git

Libevent安裝github

1. 在官網上下載對應版本的包
2. tar -zxvf /your path/libevent-xxxx-stable.tar.gz解壓
3. cd libevent-xxxx-stable
4. ./configure
5. make && make install
6. 在/usr/local/lib目錄下將動態庫的符號鏈接複製到/usr/lib/(這是爲了防止在系統找不到庫文件) windows

headers:
event2/event.h
event2/bufferevent.h後端

 

示例源碼app

 

libevent通常使用流程(簡單)

 

/**************************************************/less

evutil_socket_t    //socket 文件描述符類型

int evutil_make_socket_nonblocking(evutil_socket_t sock);

It sets O_NONBLOCK on Unixand FIONBIO on Windows.socket

int evutil_make_listen_socket_reuseable(evutil_socket_t sock);

It sets SO_REUSEADDR on Unix and does nothing on Windows.ide

/**************************************************/oop

struct event_base *event_base_new(void);

  The event_base_new() function allocates and returns a new event base with the default settings. It examines the environment
variables and returns a pointer to a new event_base. If there is an error, it returns NULL.
When choosing among methods, it picks the fastest method that the OS supports.
function is declared in <event2/event.h>.ui

/**************************************************/

void event_base_free(struct event_base *base);


  When you are finished with an event_base, you can deallocate it with event_base_free().
Note that this function does not deallocate any of the events that are currently associated with the event_base, or close any of
their sockets, or free any of their pointers.

/**************************************************/

#define EVLOOP_ONCE 0x01
#define EVLOOP_NONBLOCK 0x02
#define EVLOOP_NO_EXIT_ON_EMPTY 0x04

int event_base_loop(struct event_base *base, int flags);

  By default, the event_base_loop() function runs an event_base until there are no more events registered in it. To run the loop,
it repeatedly checks whether any of the registered events has triggered (for example, if a read event’s file descriptor is ready to
read, or if a timeout event’s timeout is ready to expire). Once this happens, it marks all triggered events as "active", and starts to
run them.

If EVLOOP_ONCE is set,
  then the loop will wait until some events become active, then run active events until there are no more to run, then return.

IfEVLOOP_NONBLOCK is set,
  then the loop will not wait for events to trigger: it will only check whether any events are ready
  to trigger immediately, and run their callbacks if so.

 

  Ordinarily, the loop will exit as soon as it has no pending or active events.You can override this behavior by passing the
EVLOOP_NO_EXIT_ON_EMPTY flag---for example, if you’re going to be adding events from some other thread. If you
do set EVLOOP_NO_EXIT_ON_EMPTY, the loop will keep running until somebody calls event_base_loopbreak(), or calls
event_base_loopexit(), or an error occurs.

When it is done, event_base_loop() returns 0 if it exited normally, -1 if it exited because of some unhandled error in the backend,
and 1 if it exited because there were no more pending or active events.

僞代碼:

while (any events are registered with the loop,or EVLOOP_NO_EXIT_ON_EMPTY was set) {
if (EVLOOP_NONBLOCK was set, or any events are already active)
If any registered events have triggered, mark them active.
else
Wait until at least one event has triggered, and mark it active.
for (p = 0; p < n_priorities; ++p) {
if (any event with priority of p is active) {
Run all active events with priority of p.
break; /* Do not run any events of a less important priority */
}
}
if (EVLOOP_ONCE was set or EVLOOP_NONBLOCK was set)
break;
}

/**************************************************/

int event_base_dispatch(struct event_base *base);

  The event_base_dispatch() call is the same as event_base_loop(), with no flags set. Thus, it keeps running until there are no more
registered events or until event_base_loopbreak() or event_base_loopexit() is called.

/**************************************************/

If you want an active event loop to stop running before all events are removed from it, you have two slightly different functions
you can call.

int event_base_loopexit(struct event_base *base,
              const struct timeval *tv);
int event_base_loopbreak(struct event_base *base);

  The event_base_loopexit() function tells an event_base to stop looping after a given time has elapsed. If the tv argument is
NULL, the event_base stops looping without a delay. If the event_base is currently running callbacks for any active events, it
will continue running them, and not exit until they have all been run.
The event_base_loopbreak() function tells the event_base to exit its loop immediately. It differs from event_base_loopexit(base,
NULL) in that if the event_base is currently running callbacks for any active events, it will exit immediately after finishing the
one it’s currently processing

Note also that event_base_loopexit(base,NULL) and event_base_loopbreak(base) act differently when no event loop is running:
loopexit schedules the next instance of the event loop to stop right after the next round of callbacks are run (as if it had been
invoked with EVLOOP_ONCE) whereas loopbreak only stops a currently running loop, and has no effect if the event loop isn’t
running.

Both of these methods return 0 on success and -1 on failure.

/**************************************************/

#define EV_TIMEOUT 0x01    //This flag indicates an event that becomes active after a timeout elapses.
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08    //Used to implement signal detection. See "Constructing signal events"
#define EV_PERSIST 0x10    //Indicates that the event is persistent. See "About Event Persistence" below
#define EV_ET 0x20    //Indicates that the event should be edge-triggered, if the underlying event_base backend supports edge-triggered events.
             //This affects the semantics of EV_READ and EV_WRITE
typedef void (*event_callback_fn)(evutil_socket_t, short, void *); struct event *event_new(struct event_base *base, evutil_socket_t fd, short what, event_callback_fn cb, void *arg);

The event_new() function tries to allocate and construct a new event for use with base. The what argument is a set of the flags
listed above. (Their semantics are described below.) If fd is nonnegative, it is the file that we’ll observe for read or write events.
When the event is active, Libevent will invoke the provided cb function, passing it as arguments: the file descriptor fd, a bitfield
of all the events that triggered, and the value that was passed in for arg when the function was constructed.
On an internal error, or invalid arguments, event_new() will return NULL.
All new events are initialized and non-pending. To make an event pending, call event_add() (documented below).
To deallocate an event, call event_free(). It is safe to call event_free() on an event that is pending or active: doing so makes the
event non-pending and inactive before deallocating it.

About Event Persistence
By default, whenever a pending event becomes active (because its fd is ready to read or write, or because its timeout expires),
it becomes non-pending right before its callback is executed. Thus, if you want to make the event pending again, you can call
event_add() on it again from inside the callback function.
If the EV_PERSIST flag is set on an event, however, the event is persistent. This means that event remains pending even when
its callback is activated. If you want to make it non-pending from within its callback, you can call event_del() on it

/**************************************************/

int event_assign(struct event *event, 
          struct event_base *base,
          evutil_socket_t fd,
          short what,           void (*callback)(evutil_socket_t, short, void *), void *arg);

All the arguments of event_assign() are as for event_new(), except for the event argument, which must point to an uninitialized
event. It returns 0 on success, and -1 on an internal error or bad arguments.

示例:

struct event *ev = event_new(NULL, -1, 0, NULL, NULL);
event_assign(ev, base, sockfd, EV_READ | EV_PERSIST,socket_read_cb, (void*)ev);

/**************************************************/

int event_add(struct event *ev, const struct timeval *tv);

Calling event_add on a non-pending event makes it pending in its configured base. The function returns 0 on success, and -1 on
failure. If tv is NULL, the event is added with no timeout. Otherwise, tv is the size of the timeout in seconds and microseconds.
If you call event_add() on an event that is already pending, it will leave it pending, and reschedule it with the provided timeout.
If the event is already pending, and you re-add it with the timeout NULL, event_add() will have no effect.

Do not set tv to the time at which you want the timeout to run. If you say "tv->tv_sec = time(NULL)+10;" on 1 January 2010,
your timeout will wait 40 years, not 10 seconds.

正確用法:

struct timeval ten_sec;
ten_sec.tv_sec = 10;
ten_sec.tv_usec = 0;
event_add(ev, &ten_sec)

 

/**************************************************/

int event_del(struct event *ev);

Calling event_del on an initialized event makes it non-pending and non-active. If the event was not pending or active, there is no
effect. The return value is 0 on success, -1 on failure.

If you delete an event after it becomes active but before its callback has a chance to execute, the callback will not be executed.

 

/**************************************************/

 

void *event_self_cbarg();

 

The event_self_cbarg() function returns a "magic" pointer which, when passed as an event callback argument, tells event_new()
to create an event receiving itself as its callback argument.

 

 

/**************************************************/

 

#ifdef WIN32
int evthread_use_windows_threads(void);
#define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED
#endif
#ifdef _EVENT_HAVE_PTHREADS
int evthread_use_pthreads(void);
#define EVTHREAD_USE_PTHREADS_IMPLEMENTED
#endif

 

If you are using the pthreads library, or the native Windows threading code, you’re in luck. There are pre-defined functions that
will set Libevent up to use the right pthreads or Windows functions for you.

 

Both functions return 0 on success, and -1 on failure.

 

 

/**************************************************/

enum event_method_feature 
{
EV_FEATURE_ET = 0x01,    //要求支持邊沿觸發的後端
EV_FEATURE_O1 = 0x02,    //要求添加、刪除單個事件,或者肯定哪一個事件激活的操做是O(1)複雜度的後端
EV_FEATURE_FDS = 0x04,    //要求支持任意文件描述符,而不單單是套接字的後端
};
int event_config_require_features(struct event_config *cfg,enum event_method_feature feature);
//讓 libevent不使用不能提供全部指定特徵的後端


int evutil_make_listen_socket_reuseable(evutil_socket_t sock);

This function makes sure that the address used by a listener socket will be available to another socket immediately after the
socket is closed. (It sets SO_REUSEADDR on Unix and does nothing on Windows. You don’t want to use SO_REUSEADDR
on Windows; it means something different there.)

/**************************************************/

tips:
  非阻塞IO:若是輸入操做不能被知足(TCP沒有一個字節到達,UDP沒有一個數據報可讀)則輸入操做返回-1 並設置EWOULDBLCOK錯誤;若是TCP鏈接被關閉,則輸入操做返回0;若是UDP收到長度爲0的數據報,則輸入操做返回0;
  對於TCP輸出操做,若是發送緩衝區沒有空間,則返回-1 並設置EWOULDBLCOK錯誤;若是發動緩衝區有不足的空間,則返回內核可以複製到該緩衝區的字節數,即不足字節數。
在某些系統中EWOULDBLCOK和EAGAIN值相同

相關文章
相關標籤/搜索