吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1039|回复: 1
收起左侧

[其他转载] libevent中的helloworld示例

[复制链接]
古月不傲 发表于 2020-11-10 13:32
本帖最后由 古月不傲 于 2020-11-10 13:37 编辑

[C] 纯文本查看 复制代码
/*
  This example program provides a trivial server program that listens for TCP
  connections on port 9995.  When they arrive, it writes a short message to
  each client connection, and closes each connection once it is flushed.

  Where possible, it exits cleanly in response to a SIGINT (ctrl-c).
*/


#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#ifndef _WIN32
#include <netinet/in.h>
# ifdef _XOPEN_SOURCE_EXTENDED
#  include <arpa/inet.h>
# endif
#include <sys/socket.h>
#endif

#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>

static const char MESSAGE[] = "Hello, World!\n";

static const int PORT = 9995;

static void listener_cb(struct evconnlistener *, evutil_socket_t,
    struct sockaddr *, int socklen, void *);
static void conn_writecb(struct bufferevent *, void *);
static void conn_eventcb(struct bufferevent *, short, void *);
static void signal_cb(evutil_socket_t, short, void *);
static void read_cb(struct bufferevent *bev, void *ctx);
int
main(int argc, char **argv)
{
        struct event_base *base;
        struct evconnlistener *listener;
        struct event *signal_event;

        struct sockaddr_in sin = {0};
#ifdef _WIN32
        WSADATA wsa_data;
        WSAStartup(0x0201, &wsa_data);
#endif
        // 分配event_base
        base = event_base_new();
        if (!base) {
                fprintf(stderr, "Could not initialize libevent!\n");
                return 1;
        }
        sin.sin_family = AF_INET;
        sin.sin_port = htons(PORT);
        // socket bind listen accpet
        listener = evconnlistener_new_bind(base, listener_cb, (void *)base,
            LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,
            (struct sockaddr*)&sin,
            sizeof(sin));
        if (!listener) {
                fprintf(stderr, "Could not create a listener!\n");
                return 1;
        }
        
        // 关联一个中断事件 
        signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);
        // 等待signal_event事件发生 NULL=永久等待 当按下ctrl+c触发中断
        if (!signal_event || event_add(signal_event, NULL)<0) {
                fprintf(stderr, "Could not create/add a signal event!\n");
                return 1;
        }
        // 循环监听event_base事件
        event_base_dispatch(base);


        // 释放
        evconnlistener_free(listener);
        event_free(signal_event);
        event_base_free(base);

        printf("done\n");
        return 0;
}

// 监听客户端的到来回调
static void
listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
    struct sockaddr *sa, int socklen, void *user_data)
{
        struct event_base *base = user_data;
        struct bufferevent *bev;
    // 创建event读写缓冲
        bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
        if (!bev) {
                fprintf(stderr, "Error constructing bufferevent!");
                event_base_loopbreak(base);
                return;
        }
    // 设置回调
        bufferevent_setcb(bev, read_cb, conn_writecb, conn_eventcb, NULL);
        bufferevent_enable(bev, EV_WRITE);  // 使可写
        bufferevent_enable(bev, EV_READ);   // 使可读

        //bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
}

// 读回调
static void read_cb(struct bufferevent *bev, void *ctx)
{
        char buf[1024] = {};
        bufferevent_read(bev, buf, 1024);
        printf("buf=%s\n", buf);
    bufferevent_write(bev, buf, sizeof(buf));
}

// 写回调
static void
conn_writecb(struct bufferevent *bev, void *user_data)
{
        struct evbuffer *output = bufferevent_get_output(bev);
        if (evbuffer_get_length(output) == 0) {
                //printf("flushed answer\n");
                //bufferevent_free(bev);
        }
}

// 连接中的事件回调
static void
conn_eventcb(struct bufferevent *bev, short events, void *user_data)
{
        if (events & BEV_EVENT_EOF) {
                printf("Connection closed.\n");
        } else if (events & BEV_EVENT_ERROR) {
                printf("Got an error on the connection: %s\n",
                    strerror(errno));/*XXX win32*/
        }
        /* None of the other events can happen here, since we haven't enabled
         * timeouts */
        bufferevent_free(bev);
}

// 事件回调
static void
signal_cb(evutil_socket_t sig, short events, void *user_data)
{
        struct event_base *base = user_data;
        struct timeval delay = { 2, 0 };

        printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");

        // 两秒后结束循环监听
        event_base_loopexit(base, &delay);
}

[Asm] 纯文本查看 复制代码
/**
  Allocate and assign a new event structure, ready to be added.

  The function event_new() returns a new event that can be used in
  future calls to event_add() and event_del().  The fd and events
  arguments determine which conditions will trigger the event; the
  callback and callback_arg arguments tell Libevent what to do when the
  event becomes active.

  If events contains one of EV_READ, EV_WRITE, or EV_READ|EV_WRITE, then
  fd is a file descriptor or socket that should get monitored for
  readiness to read, readiness to write, or readiness for either operation
  (respectively).  If events contains EV_SIGNAL, then fd is a signal
  number to wait for.  If events contains none of those flags, then the
  event can be triggered only by a timeout or by manual activation with
  event_active(): In this case, fd must be -1.

  The EV_PERSIST flag can also be passed in the events argument: it makes
  event_add() persistent until event_del() is called.

  The EV_ET flag is compatible with EV_READ and EV_WRITE, and supported
  only by certain backends.  It tells Libevent to use edge-triggered
  events.

  The EV_TIMEOUT flag has no effect here.

  It is okay to have multiple events all listening on the same fds; but
  they must either all be edge-triggered, or all not be edge triggered.

  When the event becomes active, the event loop will run the provided
  callback function, with three arguments.  The first will be the provided
  fd value.  The second will be a bitfield of the events that triggered:
  EV_READ, EV_WRITE, or EV_SIGNAL.  Here the EV_TIMEOUT flag indicates
  that a timeout occurred, and EV_ET indicates that an edge-triggered
  event occurred.  The third event will be the callback_arg pointer that
  you provide.

  @param base the event base to which the event should be attached.
  @param fd the file descriptor or signal to be monitored, or -1.
  @param events desired events to monitor: bitfield of EV_READ, EV_WRITE,
      EV_SIGNAL, EV_PERSIST, EV_ET.
  @param callback callback function to be invoked when the event occurs
  @param callback_arg an argument to be passed to the callback function

  @return a newly allocated struct event that must later be freed with
    event_free() or NULL if an error occurred.
  @see event_free(), event_add(), event_del(), event_assign()
 */

#define evsignal_new(b, x, cb, arg)                                \
        event_new((b), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg))
EVENT2_EXPORT_SYMBOL
struct event *event_new(struct event_base *base, evutil_socket_t fd, short events, event_callback_fn callback, void *callback_arg);
功能:
    分配一个新的event事件 用完要event_free()
参数:
    base:           要关联的event_base指针
    fd              要监听的文件描述符,如果什么事件都不指定,必须设置为-1
    events:         事件类型
        EV_READ:        读事件
        EV_WRITE:       写事件
        EV_PERSIST:     逗留事件 处理完以后不丢弃 需要调用event_del()
        EV_TIMEOUT:     超时事件
        EV_ET:          边缘触发事件
        EV_SIGNAL:      信号事件
        EV_CLOSED:     连接关闭事件
    callback:       回调函数   
    callback_arg:   回调参数
回调函数:
    typedef void (*event_callback_fn)(evutil_socket_t, short, void *);
    fd:     文件描述符或信号   
    events: 事件类型    
    arg:    用户参数     

/**
   Allocate a new evconnlistener object to listen for incoming TCP connections
   on a given address.

   @param base The event base to associate the listener with.
   @param cb A callback to be invoked when a new connection arrives. If the
      callback is NULL, the listener will be treated as disabled until the
      callback is set.
   @param ptr A user-supplied pointer to give to the callback.
   @param flags Any number of LEV_OPT_* flags
   @param backlog Passed to the listen() call to determine the length of the
      acceptable connection backlog.  Set to -1 for a reasonable default.
   @param sa The address to listen for connections on.
   @param socklen The length of the address.
*/

EVENT2_EXPORT_SYMBOL
struct evconnlistener *evconnlistener_new_bind(struct event_base *base,
    evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
    const struct sockaddr *sa, int socklen);
功能:
    封装socket(), bind(), listen(), accept() 用完记得evconnlistener_free()
参数:
    base:       要关联的event_base指针
    cb:         一个客户端连接到来的回调函数   
    ptr:        回调参数
    flags:      LEV_OPT_*
    backlog:    最大连接队列,-1默认合理值
    sa:         struct sockaddr
    socklen:    struct sockaddr长度
回调函数:
    typedef void (*evconnlistener_cb)(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *);
    @brief A callback that we invoke when a listener has a new connection.
    @param listener The evconnlistener
    @param fd The new file descriptor
    @param addr The source address of the connection
    @param socklen The length of addr
    @param user_arg the pointer passed to evconnlistener_new()

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

linuxcool 发表于 2020-11-11 12:21
楼主可不用它做一个线程池或者内存池
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-29 05:31

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表