zoukankan      html  css  js  c++  java
  • libev事件库使用笔记

    源码下载地址:http://dist.schmorp.de/libev/

    libev是一个高性能的事件循环库,比libevent库的性能要好。

    安装:

    1 tar -zxf libev-4.15.tar.gz
    2 cd libev-4.15
    3 ./configure
    4 make
    5 make install

    设置环境变量:

    设置一下环境变量(在文件/etc/profile中添加)。然后才可以运行。
    
    1 export LIBDIR=/usr/local/lib
    2 export LD_LIBRARY_PATH=/usr/local/lib
    3 export LD_RUN_PATH=/usr/local/lib
    
    添加完成后运行:source  /etc/profile   使设置生效;

    没有接触过libev的新手一般对概念也是比较蒙的,我也不多做介绍,教你如何快速上手

    对比说明吧!

    示例一:不使用libev

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <errno.h>
    #define DAEMON_PORT                8888
    #define MAX_LISTEN                1024
    
    char get_manager_ip[16];
    
    int adminserver();
    void pthread_adminserver(int client_sd);
    
    int main(int argc, char** argv){
        strcpy(get_manager_ip, argv[1]);
        adminserver();
    }
    int adminserver()
    {
        int ret = 0;
        int i = 0;
        int max = 0;
        int nCurrentSocket = 0;
        FILE *fp;
        int res;
        int client_sd;
        int server_sd;
        int reuse_addr;
        pthread_t p_tcpserver;
        int client_addr_size ;
    
        struct sockaddr_in client_addr;
        struct sockaddr_in server_addr;
        char line[128];
        char listen_ip[16];
        char cmd_ip[128];
        
        char *pt;
        char *edit;
    
    
        sprintf(cmd_ip,"ifconfig %s |grep 'addr:' >/get_manager_ip",get_manager_ip);
        system(cmd_ip);
    
        fp = fopen("/get_manager_ip","rb");
        if (fp == NULL) 
        {
            printf("Cann't open get_manger_ip file!
    ");  
            exit(-1);    
        }
        
        memset(line,0,128);
        fgets(line,128,fp);
        fclose(fp);
    
        pt=strstr(line, "addr:");
        if (pt != NULL)    
        {
            pt+=5;
            edit=strtok(pt," ");
            strcpy(listen_ip,edit);
        }
    
        server_sd=socket( AF_INET, SOCK_STREAM, 0 );
        
        if (server_sd < 0)
        {
            printf("ERROR: Cann't create socket!!!
    ");
            exit(-1);
        }
        
        bzero(&server_addr, sizeof(struct sockaddr));
        server_addr.sin_family = AF_INET;  
        server_addr.sin_addr.s_addr=inet_addr(listen_ip);
        server_addr.sin_port   = htons(DAEMON_PORT);  
        
        reuse_addr = 1;
        if (setsockopt (server_sd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)) < 0 )
        {
            printf("setsockopt error
    ");
            close(server_sd);
               return -1;
        }
        
        res = bind(server_sd, (struct sockaddr *)&server_addr, sizeof(server_addr));
        if (res < 0 )
        {  
            printf("Cann't bind!res = %d,erro:%d, reason:%s.
    ",res, errno, strerror(errno));  
            close(server_sd);
            exit(-1);
        }  
        
        if (listen( server_sd, MAX_LISTEN ) != 0 ) {  
            printf("Cann't listen!
    "); 
            close(server_sd);
            exit(-1);  
        }
    
        while(1)
        {
            
            client_addr_size = sizeof(client_addr);
            client_sd = accept( server_sd, (struct sockaddr *)&client_addr, (socklen_t *)&client_addr_size);
            if (pthread_create(&p_tcpserver, NULL, (void *)&pthread_adminserver, client_sd)!=0)
            {
                printf("Could not create thread check_work_time
    ");
                return ;
            } 
        }
        close(server_sd);
        exit(1);    
    }
    
    void pthread_adminserver(int client_sd)
    {
        int sockfd = 0;
        int rc;
        char buffer[4096];
         while(1)
            {             //线程处理某个客户端的连接
                memset(buffer,0,4096);
                rc=read(client_sd,buffer,4096);
                if(strlen(buffer) == 0){
                close(client_sd);  //关闭线程处理的客户端连接
                pthread_exit(0);//终止该线程
                }
                printf("read date:"%s"
    ",buffer);
                
            }
            close(client_sd);  //关闭线程处理的客户端连接
            pthread_exit(0);//终止该线程
    }

    说明:这是一个处理多并发的socket服务端,通过while接收多条连接,然后通过线程去处理每条连接,简单易懂,但是 使用两个while(1),是一件很浪费系统资源是事情;

    示例二:通过示例一改动,添加libev

    先对比两个示例先用起来吧,欢迎大神指导。

     

      1 #include <ev.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <netinet/in.h>
      6 #include <unistd.h>
      7 
      8 #define PORT 8080
      9 #define BUFFER_SIZE 1024
     10 #define MAX_CONNECTIONS 10
     11 
     12 struct ev_io *libevlist[MAX_CONNECTIONS] = {NULL};
     13 
     14 void socket_accept_callback(struct ev_loop *loop, struct ev_io *watcher, int revents);
     15 void socket_read_callback(struct ev_loop *loop, struct ev_io *watcher, int revents);
     16 /*
     17     Server                  Client
     18 
     19 
     20     socket                  socket
     21       |                       |
     22       v                       v
     23     bind                    connect
     24       |                       |
     25       v                       v
     26     listen                  write
     27       |                       |
     28       v                       v
     29     accept                  read
     30       |                       |
     31       v                       v
     32     read                    close
     33       |
     34       v
     35     write
     36       |
     37       v
     38     close
     39 */
     40 
     41 int main() {
     42     struct ev_loop *loop = ev_default_loop(0);
     43 
     44     /* socket start */
     45     int sd;
     46     struct sockaddr_in addr;
     47     int addr_len = sizeof(addr);
     48 
     49     struct ev_io *socket_watcher = (struct ev_io*)malloc(sizeof(struct ev_io));
     50     struct ev_timer *timeout_watcher = (struct ev_timer*)malloc(sizeof(struct ev_timer));
     51 
     52     // socket
     53     sd = socket(PF_INET, SOCK_STREAM, 0);
     54     if (sd < 0) {
     55         printf("socket error
    ");
     56         return -1;
     57     }
     58     bzero(&addr, sizeof(addr));
     59     addr.sin_family = AF_INET;
     60     addr.sin_port = htons(PORT);
     61     addr.sin_addr.s_addr = INADDR_ANY;
     62 
     63     // bind
     64     if (bind(sd, (struct sockaddr*) &addr, sizeof(addr)) != 0) {
     65         printf("bind error
    ");
     66         return -1;
     67     }
     68     // listen
     69     if (listen(sd, SOMAXCONN) < 0) {
     70         printf("listen error
    ");
     71         return -1;
     72     }
     73     // set sd reuseful
     74     int bReuseaddr = 1;
     75     if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (const char*) &bReuseaddr, sizeof(bReuseaddr)) != 0) {
     76         printf("setsockopt error in reuseaddr[%d]
    ", sd);
     77         return -1;
     78     }
     79     /* socket end */
     80 
     81     ev_io_init(socket_watcher, socket_accept_callback, sd, EV_READ);
     82     ev_io_start(loop, socket_watcher);
     83 
     84 //     while(1) {
     85         ev_run(loop, 0);
     86 //     }
     87 
     88     return 1;
     89 }
     90 
     91 void socket_accept_callback(struct ev_loop *loop, struct ev_io *watcher, int revents) {
     92     printf("I am: %d
    ", getpid());
     93 
     94     struct sockaddr_in client_addr;
     95     socklen_t client_len = sizeof(client_addr);
     96     int client_sd;
     97 
     98     if (EV_ERROR & revents) {
     99         printf("error event in accept
    ");
    100         return;
    101     }
    102 
    103     // socket accept: get file description
    104     client_sd = accept(watcher->fd, (struct sockaddr*) &client_addr, &client_len);
    105     if (client_sd < 0) {
    106         printf("accept error
    ");
    107         return;
    108     }
    109     // too much connections
    110     if (client_sd > MAX_CONNECTIONS) {
    111         printf("fd too large[%d]
    ", client_sd);
    112         close(client_sd);
    113         return;
    114     }
    115 
    116     if (libevlist[client_sd] != NULL) {
    117         printf("client_sd not NULL fd is [%d]
    ", client_sd);
    118         return;
    119     }
    120 
    121     printf("client connected
    ");
    122     // ev_io watcher for client
    123     struct ev_io *client_watcher = (struct ev_io*) malloc(sizeof(struct ev_io));
    124     if (client_watcher == NULL) {
    125         printf("malloc error in accept_cb
    ");
    126         return;
    127     }
    128     // listen new client
    129     ev_io_init(client_watcher, socket_read_callback, client_sd, EV_READ);
    130     ev_io_start(loop, client_watcher);
    131 
    132     libevlist[client_sd] = client_watcher;
    133 }
    134 
    135 void socket_read_callback(struct ev_loop *loop, struct ev_io *watcher, int revents) {
    136     char buffer[BUFFER_SIZE];
    137     ssize_t read;
    138 
    139     if (EV_ERROR & revents) {
    140         printf("error event in read
    ");
    141         return;
    142     }
    143     // socket recv
    144     read = recv(watcher->fd, buffer, BUFFER_SIZE, 0); // read stream to buffer
    145     if (read < 0) {
    146         printf("read error
    ");
    147         return;
    148     }
    149 
    150     if (read == 0) {
    151         printf("client disconnected.
    ");
    152 
    153         if (libevlist[watcher->fd] == NULL) {
    154             printf("the fd already freed[%d]
    ", watcher->fd);
    155         }
    156         else {
    157             printf("fd:%d will be closed!
    ",watcher->fd);
    158             close(watcher->fd);
    159             ev_io_stop(loop, libevlist[watcher->fd]);
    160             free(libevlist[watcher->fd]);
    161             libevlist[watcher->fd] = NULL;
    162         }
    163         return;
    164     }
    165     else {
    166         printf("receive message[%d]says:%s
    ",watcher->fd, buffer);
    167         if(memcmp(buffer,"quit",strlen("quit")) == 0)
    168         {
    169             printf("recv quit cmd,fd:%d will be closed!
    ",watcher->fd);
    170             close(watcher->fd);
    171             ev_io_stop(loop, libevlist[watcher->fd]);
    172             free(libevlist[watcher->fd]);
    173             libevlist[watcher->fd] = NULL;
    174             return ;
    175         }
    176     }
    177 
    178     // socket send to client
    179     send(watcher->fd, buffer, read, 0);
    180     bzero(buffer, sizeof(buffer));
    181 }
  • 相关阅读:
    TextView走马灯
    Android apk安装时出现“解析软件包错误”
    Android Studio调试手机或者安装APK的时候出现install failed test only
    如何动态改变报表的行高列宽
    如何动态的给报表添加目录
    免费报表工具零代码零基础轻松搞定 web 报表
    脚本中如何做填报数据校验
    脚本填报表的条件查询
    脚本模式下的填报表制作
    交叉填报表的制作
  • 原文地址:https://www.cnblogs.com/dpf-10/p/5341200.html
Copyright © 2011-2022 走看看