• libevent源码剖析(一)


    /*
      版本:2.1.11
      源码位置:sample/hello-world.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.
      这个例子提供一个小的服务器程序:监听9995端口上的TCP连接。
      当连接请求到来,回写一个字符串,当写缓冲区刷新后立即断开。
      Where possible, it exits cleanly in response to a SIGINT (ctrl-c).
      ctrl+c发送SIGINT信号后,程序响应信号并结束。
    */
    
    
    #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!
    ";
    
    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 *);
    
    int
    main(int argc, char **argv)
    {
        struct event_base *base;
        struct evconnlistener *listener;
        struct event *signal_event;
    
        struct sockaddr_in sin;
    #ifdef _WIN32
        WSADATA wsa_data;
        WSAStartup(0x0201, &wsa_data);
    #endif
    
        //1.创建event_base,用于对未决事件和激活事件的监视
        base = event_base_new();
        if (!base) {
            fprintf(stderr, "Could not initialize libevent!
    ");
            return 1;
        }
        //2.服务器地址
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(PORT);
    
        //3.创建监听器
        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!
    ");
            return 1;
        }
        //4.创建信号事件
        signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);
        //5.将信号事件添加到调度循环
        if (!signal_event || event_add(signal_event, NULL)<0) {
            fprintf(stderr, "Could not create/add a signal event!
    ");
            return 1;
        }
        //6.开启调度循环,监视未决事件
        event_base_dispatch(base);
        //7.释放资源
        evconnlistener_free(listener);
        event_free(signal_event);
        event_base_free(base);
    
        printf("done
    ");
        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;
    
        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, NULL, conn_writecb, conn_eventcb, NULL);
        bufferevent_enable(bev, EV_WRITE);
        bufferevent_disable(bev, EV_READ);
    
        bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
    }
    
    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
    ");
            bufferevent_free(bev);
        }
    }
    
    static void
    conn_eventcb(struct bufferevent *bev, short events, void *user_data)
    {
        if (events & BEV_EVENT_EOF) {
            printf("Connection closed.
    ");
        } else if (events & BEV_EVENT_ERROR) {
            printf("Got an error on the connection: %s
    ",
                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.
    ");
    
        event_base_loopexit(base, &delay);
    }

      

     

  • 相关阅读:
    C++课程学习笔记第六周:多态
    C++课程学习笔记第五周:继承
    C++课程学习笔记第四周:运算符的重载
    C++课程学习笔记第三周:类和对象提高
    C++课程学习笔记第一周:从C到C++
    C++课程学习笔记第二周:类和对象基础
    PyTorch的安装及学习资料
    PyTorch练手项目一:训练一个简单的线性回归
    PyTorch练手项目二:MNIST手写数字识别
    PyTorch练手项目四:孪生网络(Siamese Network)
  • 原文地址:https://www.cnblogs.com/orejia/p/12348969.html
Copyright © 2020-2023  润新知