日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

libevent的簡(jiǎn)單應(yīng)用

系統(tǒng) 1879 0

本文轉(zhuǎn)載自:?http://blog.csdn.net/liuguanghui1988/article/details/7090531

Libevent的應(yīng)用主要圍繞幾大事件:超時(shí)事件、信號(hào)事件、讀/寫事件。

下面就一一簡(jiǎn)單介紹一下它們的使用。

超時(shí)事件

示例:

      
        /*
      
      
        

 * Compile with:

 * gcc  time-test time-test.c -o time-test time-test  -I/usr/local/include  -L/usr/local/lib  -levent

 
      
      
        */
      
      
        /*
      
      
        

 * XXX This sample code was once meant to show how to use the basic Libevent

 * interfaces, but it never worked on non-Unix platforms, and some of the

 * interfaces have changed since it was first written.  It should probably

 * be removed or replaced with something better.

 *

 * Compile with:

 * gcc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent

 
      
      
        */
      
      
        



#include 
      
      <sys/types.h>
      
        

#include 
      
      <sys/stat.h>
      
        

#include 
      
      <time.h>
      
        

#ifdef _EVENT_HAVE_SYS_TIME_H

#include 
      
      <sys/time.h>


      
        #endif
      
      
        

#include 
      
      <stdio.h>
      
        

#include 
      
      <event2/
      
        event
      
      .h>
      
        

#include 
      
      <event2/event_struct.h>
      
        

#include 
      
      <event2/util.h>




      
        struct
      
      
         timeval lasttime;


      
      
        int
      
      
         event_is_persistent;




      
      
        static
      
      
        void
      
       timeout_cb(evutil_socket_t fd, 
      
        short
      
      
        event
      
      , 
      
        void
      
       *
      
        arg)

{

    
      
      
        struct
      
      
         timeval newtime, difference;

    
      
      
        struct
      
      
        event
      
       *timeout =
      
         arg;

    
      
      
        double
      
      
         elapsed;



    evutil_gettimeofday(
      
      &
      
        newtime, NULL);

    evutil_timersub(
      
      &newtime, &lasttime, &
      
        difference);

    elapsed 
      
      = difference.tv_sec +
      
        

        (difference.tv_usec 
      
      / 
      
        1.0e6
      
      
        );



    printf(
      
      
        "
      
      
        timeout_cb called at %d': %.3f seconds elapsed.\n
      
      
        "
      
      
        ,

        (
      
      
        int
      
      
        )newtime.tv_sec, elapsed);

    lasttime 
      
      =
      
         newtime;


      
      
        //
      
      
          /* 啟動(dòng)此測(cè)試程序時(shí),不加-p參數(shù),使用以下代碼也可實(shí)現(xiàn)相同功能 */


      
      
        //
      
      
            struct timeval tv;


      
      
        //
      
      
            evutil_timerclear(&tv);


      
      
        //
      
      
            tv.tv_sec = 1;


      
      
        //
      
      
            event_add(timeout, &tv);    
      
      
        //
      
      
        再次添加定時(shí)事件
      
      
        }




      
      
        int
      
       main(
      
        int
      
       argc, 
      
        char
      
       **
      
        argv)

{

    
      
      
        struct
      
      
        event
      
       timeout;        
      
        //
      
      
        創(chuàng)建事件
      
      
        struct
      
      
         timeval tv;

    
      
      
        struct
      
       event_base *
      
        base
      
      ;    
      
        //
      
      
        創(chuàng)建事件"總管"的指針
      
      
        int
      
       flags;                    
      
        //
      
      
        事件標(biāo)志,超時(shí)事件可不設(shè)EV_TIMEOUT,因?yàn)樵谔砑邮录r(shí)可設(shè)置
      
      
        if
      
       (argc == 
      
        2
      
       && !strcmp(argv[
      
        1
      
      ], 
      
        "
      
      
        -p
      
      
        "
      
      
        )) {

        event_is_persistent 
      
      = 
      
        1
      
      
        ;

        flags 
      
      = EV_PERSIST;        
      
        //
      
      
        使得事件具有持久性(否則事件只會(huì)調(diào)度一次)
      
      

    } 
      
        else
      
      
         {

        event_is_persistent 
      
      = 
      
        0
      
      
        ;

        flags 
      
      = 
      
        0
      
      
        ;

    }

    
      
      
        /*
      
      
         Initalize the event library 
      
      
        */
      
      
        base
      
       = event_base_new();            
      
        //
      
      
        創(chuàng)建事件"總管"
      
      
        /*
      
      
         Initalize one event 
      
      
        */
      
      
        

    event_assign(
      
      &timeout, 
      
        base
      
      , -
      
        1
      
      , flags, timeout_cb, (
      
        void
      
      *) &
      
        timeout);

    evutil_timerclear(
      
      &
      
        tv);

    tv.tv_sec 
      
      = 
      
        1
      
      
        ;

    event_add(
      
      &timeout, &tv);        
      
        //
      
      
        添加事件,同時(shí)設(shè)置超時(shí)時(shí)間
      
      

    evutil_gettimeofday(&
      
        lasttime, NULL);

    event_base_dispatch(
      
      
        base
      
      );        
      
        //
      
      
        循環(huán)監(jiān)視事件,事件標(biāo)志的條件發(fā)生,就調(diào)用回調(diào)函數(shù)
      
      
        return
      
       (
      
        0
      
      
        );

}
      
    

?/*******************************************************/

啟動(dòng)進(jìn)程:

[lgh@localhost test]$ ./libe_timer_test -p

結(jié)果:

timeout_cb called at 1325693811': 1.000 seconds elapsed.

timeout_cb called at 1325693812': 1.000 seconds elapsed.

timeout_cb called at 1325693813': 1.001 seconds elapsed.

timeout_cb called at 1325693814': 1.000 seconds elapsed.

timeout_cb called at 1325693815': 1.000 seconds elapsed.

以一行/秒的速率打印以上信息,也就是每秒打印一行。因?yàn)槌瑫r(shí)為一秒。

==============================

啟動(dòng)進(jìn)程:

[lgh@localhost test]$ ./libe_timer_test

結(jié)果:

timeout_cb called at 1325693516: 1.000 seconds elapsed.

沒(méi)有-p參數(shù),事件只調(diào)度一次。如果不加EV_PERSIST標(biāo)志也想實(shí)現(xiàn)事件的持續(xù)性,還有一種辦法,就是在回調(diào)函數(shù)的后面再添加該事件,即上面回調(diào)函數(shù)的批量注釋代碼。

?

信號(hào)事件

示例:

      
        /*
      
      
        

 * Compile with:

 *  gcc libe_signal_test.c -o libe_signal_test -I/usr/local/include -L/usr/local/lib -levent

 
      
      
        */
      
      
        

#include 
      
      <signal.h>
      
        

#include 
      
      <stdio.h>
      
        

#include 
      
      <
      
        event
      
      .h>
      
        

#include 
      
      <event2/
      
        event
      
      .h>
      
        

#ifdef _EVENT___func__


      
      
        #define
      
       __func__ _EVENT___func__


      
        #endif
      
      
        //
      
      
        int called = 0;
      
      
        static
      
      
        void
      
       signal_cb(evutil_socket_t fd, 
      
        short
      
      
        event
      
      , 
      
        void
      
       *
      
        arg)

{

    
      
      
        struct
      
      
        event
      
       *signal =
      
         arg;

    sleep(
      
      
        10
      
      
        );

    printf(
      
      
        "
      
      
        %s: got signal %d\n
      
      
        "
      
      
        , __func__, EVENT_SIGNAL(signal));




      
      
        //
      
      
            if (called >= 2)


      
      
        //
      
      
                event_del(signal);


      
      
        //
      
      
            called++;
      
      
        }




      
      
        int
      
       main(
      
        int
      
       argc, 
      
        char
      
       **
      
        argv)

{

    
      
      
        struct
      
      
        event
      
      
         signal_usr;

    
      
      
        struct
      
       event_base* 
      
        base
      
      
        ;



    
      
      
        /*
      
      
         Initalize the event library 
      
      
        */
      
      
        base
      
       =
      
         event_base_new();

    
      
      
        /*
      
      
         Initalize one event 
      
      
        */
      
      
        

    event_assign(
      
      &signal_usr, 
      
        base
      
      , SIGUSR1, EV_SIGNAL|
      
        EV_PERSIST, signal_cb,

        
      
      &
      
        signal_usr);

    event_add(
      
      &
      
        signal_usr, NULL);

    event_base_dispatch(
      
      
        base
      
      
        );

    event_base_free(
      
      
        base
      
      
        );

    printf(
      
      
        "
      
      
        end of main!\n
      
      
        "
      
      
        );

    
      
      
        return
      
       (
      
        0
      
      
        );

}
      
    

啟動(dòng)進(jìn)程:

[lgh@localhost test]$ ./libe_signal_test &

[1] 2998

用kill -10 2998命令給進(jìn)程發(fā)送信號(hào)SIGUSR1,進(jìn)程的的執(zhí)行結(jié)果如下:

[lgh@localhost test]$ kill -10 2998

[lgh@localhost test]$ kill -10 2998

signal_cb: got signal 10

?[lgh@localhost test]$ kill -10 2998

signal_cb: got signal 10

[lgh@localhost test]$ signal_cb: got signal 10

給進(jìn)程發(fā)送了3次SIGUSR1信號(hào),信號(hào)回調(diào)函數(shù)執(zhí)行了三次(其中最后一行隔了幾秒才打印出來(lái))。這說(shuō)明libevent對(duì)linux中的不可靠信號(hào)也是支持排隊(duì)的。

?

讀/寫事件

文件描述符是否可讀/寫,這個(gè)不太好模擬(可能用文件的讀/寫鎖可以實(shí)現(xiàn)模擬,鄙人目前還沒(méi)有嘗試過(guò),有試過(guò)的朋友可以指點(diǎn)一下),有一種方法就是用socket連接來(lái)模擬,先建立一個(gè)服務(wù)端和客戶端,當(dāng)服務(wù)端的監(jiān)聽端口可讀時(shí)說(shuō)明有一個(gè)新的連接請(qǐng)求。

示例:

?服務(wù)端——proc_server.c

      #include <sys/socket.h>
      
        

#include 
      
      <sys/types.h>
      
        

#include 
      
      <netinet/
      
        in
      
      .h>
      
        

#include 
      
      <stdio.h>
      
        

#include 
      
      <
      
        event
      
      .h>
      
        

#include 
      
      <event2/
      
        event
      
      .h>
      
        

#include
      
      <errno.h>




      
        #define
      
       PORT            6666            
      
        //
      
      
        ----------需改靈活點(diǎn)
      
      
        #define
      
       BACKLOG         10                
      
        //
      
      
        好像沒(méi)起到作用,我設(shè)置為1,在同一機(jī)子下開兩個(gè)連接,沒(méi)彈出警告信息
      
      
        #define
      
       EV_BUFSIZE_T       sizeof(pid_t)    
      
        //
      
      
        服務(wù)端與客戶端傳遞數(shù)據(jù)的buffer大小
      
      
        /*
      
      
         管理每一個(gè)連接的讀寫事件和數(shù)據(jù) 
      
      
        */
      
      
        

typedef 
      
      
        struct
      
      
         sock_event {

    
      
      
        struct
      
      
        event
      
       *read_ev;        
      
        //
      
      
        讀事件
      
      
        struct
      
      
        event
      
       *write_ev;        
      
        //
      
      
        寫事件
      
      

    pid_t *buffer;                
      
        //
      
      
        buffer僅存進(jìn)程pid
      
      
        int
      
          gapbeats;                
      
        //
      
      
        定時(shí)間隔
      
      
        int
      
          maxbeats;                
      
        //
      
      
        在客戶端不工作或退出的情況下,服務(wù)端的最大檢測(cè)次數(shù)
      
      
        int
      
          pastbeats;                
      
        //
      
      
        沒(méi)有收到數(shù)據(jù)的情況下,當(dāng)前的心跳檢測(cè)數(shù)
      
      
        }sock_ev;




      
      
        struct
      
       event_base* 
      
        base
      
      ;        
      
        //
      
      
        管理所有連接事件
      
      
        /*
      
      
         釋放堆分配的sock_ev結(jié)構(gòu)體 
      
      
        */
      
      
        void
      
       release_sock_ev(sock_ev *
      
        ev)

{

    event_del(ev
      
      ->
      
        read_ev);

    free(ev
      
      ->
      
        read_ev);

    event_del(ev
      
      ->
      
        write_ev);    

    free(ev
      
      ->
      
        write_ev);

    free(ev
      
      ->
      
        buffer);

    free(ev);

}




      
      
        /*
      
      
         功能:創(chuàng)建一個(gè)sock_ev結(jié)構(gòu)體,并且將它初始化.

 * 參數(shù):gapbeats,服務(wù)端兩個(gè)檢測(cè)心跳的間隔時(shí)間(單位:秒);

 *        maxbeats,沒(méi)有收到客戶端數(shù)據(jù)的最大檢測(cè)次數(shù).

 * 返回:sock_ev結(jié)構(gòu)體指針.

 
      
      
        */
      
      
        

sock_ev
      
      * create_sock_ev(
      
        int
      
       gapbeats, 
      
        int
      
      
         maxbeats)

{

    sock_ev 
      
      * se = (sock_ev *)malloc(
      
        sizeof
      
      
        (sock_ev));    

    
      
      
        if
      
       (!
      
        se)

        
      
      
        return
      
      
         NULL;

    memset(se, 
      
      
        0
      
      , 
      
        sizeof
      
      
        (sock_ev));

    se
      
      ->read_ev = (
      
        struct
      
      
        event
      
      *)malloc(
      
        sizeof
      
      (
      
        struct
      
      
        event
      
      
        ));

    se
      
      ->write_ev = (
      
        struct
      
      
        event
      
      *)malloc(
      
        sizeof
      
      (
      
        struct
      
      
        event
      
      
        ));

    se
      
      ->buffer = (pid_t *
      
        )malloc(EV_BUFSIZE_T);

    
      
      
        if
      
       (!se->read_ev || !se->write_ev || !se->
      
        buffer)

        
      
      
        return
      
      
         NULL;

    memset(se
      
      ->read_ev, 
      
        0
      
      , 
      
        sizeof
      
      (
      
        struct
      
      
        event
      
      
        ));

    memset(se
      
      ->write_ev, 
      
        0
      
      , 
      
        sizeof
      
      (
      
        struct
      
      
        event
      
      
        ));

    memset(se
      
      ->buffer, 
      
        0
      
      
        , EV_BUFSIZE_T);

    se
      
      ->gapbeats =
      
         gapbeats;

    se
      
      ->maxbeats =
      
         maxbeats;

    se
      
      ->pastbeats = 
      
        0
      
      
        ;



    
      
      
        return
      
      
         se;    

}




      
      
        /*
      
      
         功能:寫事件回調(diào)函數(shù)

 * 參數(shù):libevent回調(diào)函數(shù)的三個(gè)典型參數(shù)

 *         sock,文件描述符;event,事件類型(EV_WRITE);arg,傳給函數(shù)的數(shù)據(jù)指針(buffer)

 * 返回: void (libevent回調(diào)函數(shù)的返回為void)


      
      
        */
      
      
        void
      
       socket_write(
      
        int
      
       sock, 
      
        short
      
      
        event
      
      , 
      
        void
      
      *
      
         arg)

{

    pid_t
      
      *
      
         buffer;

    
      
      
        if
      
       (!
      
        arg)

        
      
      
        return
      
      
        ;

        

    buffer 
      
      = (pid_t*
      
        )arg;

    
      
      
        if
      
       (send(sock, buffer, 
      
        sizeof
      
      (*buffer), 
      
        0
      
      ) < 
      
        0
      
      
        ) {

        printf(
      
      
        "
      
      
        server send msg error: errno %d--%s\n
      
      
        "
      
      
        , errno, strerror(errno));    

        
      
      
        return
      
      
        ; 

    }

    memset(buffer, 
      
      
        0
      
      , 
      
        sizeof
      
      (*
      
        buffer));

}




      
      
        /*
      
      
         功能:讀事件回調(diào)函數(shù)

 * 參數(shù):libevent回調(diào)函數(shù)的三個(gè)典型參數(shù)

 *         sock,文件描述符;event,事件類型(EV_READ);arg,傳給函數(shù)的數(shù)據(jù)指針(sock_ev)

 * 返回: void.


      
      
        */
      
      
        void
      
       socket_read(
      
        int
      
       sock, 
      
        short
      
      
        event
      
      , 
      
        void
      
      *
      
         arg)

{

    
      
      
        int
      
      
         size;

    sock_ev
      
      * sockev = (sock_ev*
      
        )arg;

    
      
      
        if
      
      (!
      
        sockev)

        
      
      
        return
      
      
        ;

        

    memset(sockev
      
      ->buffer, 
      
        0
      
      
        , EV_BUFSIZE_T);

    size 
      
      = recv(sock, sockev->buffer, EV_BUFSIZE_T, 
      
        0
      
      
        );

    
      
      
        if
      
       (size <= 
      
        0
      
      ) {            
      
        //
      
      
        接收數(shù)據(jù)失敗
      
      

        sockev->pastbeats++;                
      
        //
      
      
        全局變量
      
      

        printf(
      
        "
      
      
        pastbeats:\t%d\n
      
      
        "
      
      , sockev->pastbeats);        
      
        //
      
      
        --debug
      
      
        if
      
       (sockev->pastbeats >= sockev->
      
        maxbeats) {        

            printf(
      
      
        "
      
      
        ---client error or exit:please restart\n
      
      
        "
      
      );    
      
        //
      
      
        --debug
      
      
                    release_sock_ev(sockev);

            close(sock);

        }

        
      
      
        return
      
      
        ;

    }

    sockev
      
      ->pastbeats = 
      
        0
      
      
        ;

    printf(
      
      
        "
      
      
        pastbeats:\t%d\n
      
      
        "
      
      , sockev->pastbeats);            
      
        //
      
      
        --debug
      
      

    printf(
      
        "
      
      
        receive data:\t%d    size:\t%d\n
      
      
        "
      
      , *sockev->
      
        buffer, size);

    event_add(sockev
      
      ->write_ev, NULL);            
      
        //
      
      
        添加端口寫事件,將數(shù)據(jù)返回給客戶端
      
      
        }




      
      
        /*
      
      
         功能:接受新連接請(qǐng)求

 * 參數(shù):libevent回調(diào)函數(shù)的三個(gè)典型參數(shù)

 *         sock,文件描述符;event,事件類型(EV_READ,監(jiān)聽端口可讀,表示有新連接請(qǐng)求);

         arg,目前為空指針.

 * 返回: void.


      
      
        */
      
      
        void
      
       connect_accept(
      
        int
      
       sock, 
      
        short
      
      
        event
      
      , 
      
        void
      
      *
      
         arg)

{

    
      
      
        struct
      
      
         sockaddr_in cli_addr;

    
      
      
        int
      
      
         connetfd, sin_size;

    
      
      
        struct
      
       timeval beat;                
      
        //
      
      
        定時(shí)讀事件,來(lái)檢測(cè)客戶端發(fā)送了數(shù)據(jù)
      
      

    sock_ev* sockev;                      
      
        //
      
      
        為連接建立端口事件
      
      
        if
      
       ((sockev = create_sock_ev(
      
        1
      
      , 
      
        10
      
      )) ==
      
         NULL)

        
      
      
        return
      
      
        ;

    sin_size 
      
      = 
      
        sizeof
      
      (
      
        struct
      
      
         sockaddr_in);    

    connetfd 
      
      = accept(sock, (
      
        struct
      
       sockaddr*)&cli_addr, &
      
        sin_size);

    
      
      
        if
      
       (connetfd == -
      
        1
      
      
        ) {

        printf(
      
      
        "
      
      
        server accept() error: errno %d--%s\n
      
      
        "
      
      
        , errno, strerror(errno));    

        
      
      
        return
      
      
        ;

    }  

    event_assign(sockev
      
      ->read_ev, 
      
        base
      
      
        , connetfd, EV_PERSIST, socket_read, sockev);  

    
      
      
        //
      
      
        下面是老版接口    


      
      
        //
      
      
            event_set(sockev->read_ev, connetfd, EV_PERSIST, socket_read, sockev);        
      
      
        //
      
      
        讀事件  (若加上EV_READ|,則定時(shí)讀會(huì)失效)


      
      
        //
      
      
            event_base_set(base, sockev->read_ev);  
      
      

    evutil_timerclear(&
      
        beat);

    beat.tv_sec 
      
      = sockev->gapbeats;             
      
        //
      
      
        定期檢查端口是否可讀,來(lái)判斷客戶端是否存在
      
      

    event_add(sockev->read_ev, &
      
        beat);

    

    event_assign(sockev
      
      ->write_ev, 
      
        base
      
      , connetfd, EV_WRITE, socket_write, sockev->buffer);                                                                              
      
        //
      
      
        寫事件


      
      
        //
      
      
            event_set(sockev->write_ev, connetfd, EV_WRITE, socket_write, sockev->buffer);    


      
      
        //
      
      
            event_base_set(base, sockev->write_ev);                                          
      
      
        }




      
      
        int
      
       main(
      
        int
      
       argc, 
      
        char
      
      *
      
         argv[])

{

    
      
      
        struct
      
      
         sockaddr_in server_addr;

    
      
      
        int
      
      
         sock;


      
      
        //
      
      
            struct event listen_ev;        
      
      
        //
      
      
        創(chuàng)建連接請(qǐng)求監(jiān)聽事件
      
      
        struct
      
      
        event
      
       *
      
        listen_ev;

    

    sock 
      
      = socket(AF_INET, SOCK_STREAM, 
      
        0
      
      
        );

    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (
      
      
        int
      
       *)
      
        1
      
      , 
      
        sizeof
      
      (
      
        int
      
      
        ));

    memset(
      
      &server_addr, 
      
        0
      
      , 
      
        sizeof
      
      
        (server_addr));

    server_addr.sin_family 
      
      =
      
         AF_INET;

    server_addr.sin_port 
      
      =
      
         htons(PORT);

    server_addr.sin_addr.s_addr 
      
      =
      
         INADDR_ANY;

    
      
      
        if
      
       (bind(sock, (
      
        struct
      
       sockaddr*)&server_addr, 
      
        sizeof
      
      (
      
        struct
      
       sockaddr)) == -
      
        1
      
      
        ) {

        printf(
      
      
        "
      
      
        bind socket error: errno %d--%s\n
      
      
        "
      
      
        , errno, strerror(errno));    

        exit(
      
      
        0
      
      
        ); 

    }

    
      
      
        if
      
       (listen(sock, BACKLOG) == -
      
        1
      
      
        ) {

        printf(
      
      
        "
      
      
        listen socket error: errno %d--%s\n
      
      
        "
      
      
        , errno, strerror(errno));    

        exit(
      
      
        0
      
      
        );

    }



    
      
      
        base
      
       = event_base_new();    
      
        //
      
      
        base,全局變量.
      
      

    listen_ev = event_new(
      
        base
      
      , sock, EV_READ|EV_PERSIST, connect_accept, NULL);    
      
        //
      
      
        創(chuàng)建evnet對(duì)象并初始化
      
      
        if
      
       (!
      
        listen_ev) {

        printf(
      
      
        "
      
      
        event_new() fail\n
      
      
        "
      
      
        );

        exit(
      
      
        0
      
      
        );

    }


      
      
        //
      
      
            event_set(&listen_ev, sock, EV_READ|EV_PERSIST, connect_accept, NULL); 這是老接口


      
      
        //
      
      
            event_base_set(base, &listen_ev);
      
      

    event_add(listen_ev, NULL);        
      
        //
      
      
        添加到監(jiān)視事件集中,event就變成的未決狀態(tài)
      
      

    event_base_dispatch(
      
        base
      
      );        
      
        //
      
      
        輪詢監(jiān)視所有事件
      
      
        if
      
      (event_del(listen_ev) == 
      
        0
      
      ) {    
      
        //
      
      
        從監(jiān)視事件集中刪除
      
      

        event_free(listen_ev);        
      
        //
      
      
        刪除事件,釋放空間
      
      
            }

    event_base_free(
      
      
        base
      
      );            
      
        //
      
      
        刪除base對(duì)象
      
      

    exit(
      
        0
      
      
        );

}
      
    

客戶端:proc_client.c

      #include<stdio.h>
      
        

#include
      
      <stdlib.h>
      
        

#include
      
      <
      
        string
      
      .h>
      
        

#include
      
      <errno.h>
      
        

#include
      
      <sys/types.h>
      
        

#include
      
      <sys/socket.h>
      
        

#include
      
      <netinet/
      
        in
      
      .h>
      
        

#include 
      
      <
      
        event
      
      .h>
      
        

#include 
      
      <event2/
      
        event
      
      .h>
      
        

#include 
      
      <event2/util.h>




      
        #define
      
       MAXLINE 1024




      
        static
      
      
        void
      
       heartbit_cb(evutil_socket_t fd, 
      
        short
      
      
        event
      
      , 
      
        void
      
       *
      
        arg);




      
      
        int
      
       main(
      
        int
      
       argc, 
      
        char
      
      **
      
         argv)

{

    
      
      
        int
      
      
         sockfd, n, received; 

    
      
      
        int
      
      
         len, bytes;   

    
      
      
        char
      
      
         recvline[MAXLINE], sendline[MAXLINE]; 

    pid_t tests 
      
      =
      
         getpid(); 

    pid_t 
      
      *pids = &
      
        tests; 

    pid_t testr 
      
      = 
      
        0
      
      
        ; 

    pid_t 
      
      *pidr = &
      
        testr; 

    
      
      
        struct
      
      
         sockaddr_in    servaddr;  

    
      
      
        struct
      
      
         timeval tv; 

    
      
      
        struct
      
       event_base* 
      
        base
      
      
        ;

    
      
      
        struct
      
      
        event
      
       *
      
        client_ev;

    

    
      
      
        if
      
      ( argc != 
      
        2
      
      
        ){    

        printf(
      
      
        "
      
      
        usage: ./client <ip address>\n
      
      
        "
      
      
        );    

        exit(
      
      
        0
      
      
        );    

    }    



    memset(sendline, 
      
      
        0
      
      
        , MAXLINE);

    
      
      
        if
      
      ( (sockfd = socket(AF_INET, SOCK_STREAM, 
      
        0
      
      )) < 
      
        0
      
      
        ){    

        printf(
      
      
        "
      
      
        create socket error: %s(errno: %d)\n
      
      
        "
      
      
        , strerror(errno),errno);    

        exit(
      
      
        0
      
      
        );    

    }    

    memset(
      
      &servaddr, 
      
        0
      
      , 
      
        sizeof
      
      
        (servaddr));    

    servaddr.sin_family 
      
      =
      
         AF_INET;    

    servaddr.sin_port 
      
      = htons(
      
        6666
      
      );   
      
        //
      
      
        把16位值從主機(jī)字節(jié)序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序 
      
      
        if
      
      ( inet_pton(AF_INET, argv[
      
        1
      
      ], &servaddr.sin_addr) <= 
      
        0
      
      ){   
      
        //
      
      
         [將“點(diǎn)分十進(jìn)制”ip-> 網(wǎng)絡(luò)字節(jié)序“整數(shù)”ip] 
      
      

        printf(
      
        "
      
      
        inet_pton error for %s\n
      
      
        "
      
      ,argv[
      
        1
      
      
        ]);    

        exit(
      
      
        0
      
      
        );    

    }    

    
      
      
        if
      
      ( connect(sockfd, (
      
        struct
      
       sockaddr*)&servaddr, 
      
        sizeof
      
      (servaddr)) < 
      
        0
      
      
        ){    

        printf(
      
      
        "
      
      
        connect error: %s(errno: %d)\n
      
      
        "
      
      
        ,strerror(errno),errno);    

        exit(
      
      
        0
      
      
        );    

    }    

    printf(
      
      
        "
      
      
        send msg to server: \n
      
      
        "
      
      
        );  

    evutil_timerclear(
      
      &
      
        tv);

    tv.tv_sec 
      
      = 
      
        2
      
      
        ;

    

    
      
      
        base
      
       =
      
         event_base_new();

    client_ev 
      
      = event_new(
      
        base
      
      
        , sockfd, EV_PERSIST, heartbit_cb, pids);

    
      
      
        if
      
       (!
      
        client_ev) {

        printf(
      
      
        "
      
      
        event_new() fail\n
      
      
        "
      
      
        );

        exit(
      
      
        0
      
      
        );

    }


      
      
        //
      
      
            event_set(&client_ev, sockfd, EV_PERSIST, heartbit_cb, pids); 
      
      
        //
      
      
        若加上EV_WRITE|,sockfd可寫,則會(huì)一直寫(與定時(shí)事件是關(guān)系或) EV_PERSIST


      
      
        //
      
      
            event_base_set(base, &client_ev);
      
      

    event_add(client_ev, &
      
        tv);

    event_base_dispatch(
      
      
        base
      
      
        );

    

    
      
      
        if
      
      (event_del(client_ev) == 
      
        0
      
      
        ) {

        event_free(client_ev);

    }

    event_base_free(
      
      
        base
      
      
        );

    close(sockfd);    

    exit(
      
      
        0
      
      
        );

}




      
      
        /*
      
      
         功能: 向服務(wù)端發(fā)送心跳包

 * 參數(shù): 

 *

 
      
      
        */
      
      
        static
      
      
        void
      
       heartbit_cb(evutil_socket_t fd, 
      
        short
      
      
        event
      
      , 
      
        void
      
       *
      
        arg)

{

    pid_t 
      
      *pid = (pid_t *
      
        )arg; 

    pid_t testr 
      
      = 
      
        0
      
      
        ; 

    pid_t 
      
      *pid_recv = &
      
        testr; 

    
      
      
        int
      
      
         len;



    len 
      
      = 
      
        sizeof
      
      
        (pid_t);

    
      
      
        if
      
      ( send(fd, pid, len, 
      
        0
      
      ) !=
      
         len) {    

        printf(
      
      
        "
      
      
        send msg error: %s(errno: %d)\n
      
      
        "
      
      
        , strerror(errno), errno);    

        exit(
      
      
        0
      
      
        );    

    }

    
      
      
        //
      
      
        接收從服務(wù)端的返回?cái)?shù)據(jù)      
      
      

    fputs(
      
        "
      
      
        echo from server:\n
      
      
        "
      
      
        , stdout);

    
      
      
        if
      
      (recv(fd, pid_recv, len, 
      
        0
      
      ) < 
      
        0
      
      
        ) {

        printf(
      
      
        "
      
      
        Failed to receive bytes from client\n
      
      
        "
      
      
        );

        exit(
      
      -
      
        1
      
      
        );

    } 

    printf(
      
      
        "
      
      
        %d\n
      
      
        "
      
      , *
      
        pid_recv);

    fputs(
      
      
        "
      
      
        \n
      
      
        "
      
      
        , stdout);     

    

}
      
    

結(jié)果:

[lgh@localhost proc]$ ./proc_client 192.168.1.107
send msg to server:
echo from server:
7482

echo from server:
7482

echo from server:
7482

--------------------------------------------------------------------------------------------

[lgh@localhost proc]$ ./proc_server
pastbeats: 0
receive data:7482?????? size:4
pastbeats: 0
receive data:7482?????? size:4
pastbeats: 0
receive data:7482?????? size:4
pastbeats: 1
pastbeats: 2
pastbeats: 3
pastbeats: 4
pastbeats: 5
pastbeats: 6
pastbeats: 7
pastbeats: 8
pastbeats: 9
pastbeats: 10
---pastbeats > maxbeats
=============================================================

測(cè)試設(shè)置:客戶端每2秒發(fā)一次心跳,服務(wù)端每1秒去查看端口是否可讀.?
??????????????????? 服務(wù)端若經(jīng)過(guò)10次還沒(méi)收到心跳,則認(rèn)為客戶端已退出.
?測(cè)試過(guò)程:先讓客戶端發(fā)3次心跳,再終止掉客戶端.---用時(shí)6秒。
? ??????????????? ??此時(shí),服務(wù)端已經(jīng)對(duì)端口發(fā)起了6次檢測(cè),有3次接收到了數(shù)據(jù),有3次沒(méi)有收到數(shù)據(jù)。
? ?????????????????? 當(dāng)終止掉客戶端后,服務(wù)端每次檢測(cè)都會(huì)收不到數(shù)據(jù),現(xiàn)象是:前3次是連續(xù)執(zhí)行了超時(shí)回調(diào)函數(shù)socket_read,這3次沒(méi)有經(jīng)過(guò)每隔1秒執(zhí)行。
? ?????????????????? 后面再每秒檢測(cè)7次,即每秒執(zhí)行一次回調(diào)函數(shù)。總計(jì)10次沒(méi)有收到來(lái)自客戶端的數(shù)據(jù),判斷客戶端已退出。
?
? 測(cè)試結(jié)果判斷: libevent對(duì)定時(shí)事件支持排隊(duì),即有多少次定時(shí),它就執(zhí)行回調(diào)函數(shù)多少次.
? 編程建議:服務(wù)端的心跳頻率要小于等于客戶端的心跳頻率.(小于,會(huì)有丟包現(xiàn)象,但我們的需求只是檢測(cè)客戶端是否存在)

?

小結(jié):這個(gè)小例子用來(lái)做進(jìn)程管理,客戶端是不行的,因?yàn)檫@里的客戶端也是libevent的超時(shí)事件,它在輪詢超時(shí)事件的時(shí)候會(huì)一直占用進(jìn)程的cpu,所以這樣是不行的,所以客戶端的定時(shí)發(fā)送心跳包應(yīng)該改用信號(hào)做成一個(gè)小模塊加入到客戶端進(jìn)程中。

libevent的簡(jiǎn)單應(yīng)用


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 连江县| 女性| 新宁县| 安溪县| 横峰县| 乌兰县| 潜江市| 寿光市| 邹城市| 武穴市| 虎林市| 安新县| 桐梓县| 迁西县| 焉耆| 长治市| 乐陵市| 宕昌县| 莒南县| 屏东市| 柳河县| 韶山市| 资阳市| 平安县| 临潭县| 平武县| 大理市| 永兴县| 织金县| 绍兴县| 拜泉县| 武义县| 湾仔区| 夏河县| 蓬莱市| 姜堰市| 卓尼县| 砀山县| 山丹县| 滕州市| 安康市|