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!\n");  
        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!!!\n");
        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\n");
        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.\n",res, errno, strerror(errno));  
        close(server_sd);
        exit(-1);
    }  
    
    if (listen( server_sd, MAX_LISTEN ) != 0 ) {  
        printf("Cann't listen!\n"); 
        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\n");
            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\"\n",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\n");
 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\n");
 66         return -1;
 67     }
 68     // listen
 69     if (listen(sd, SOMAXCONN) < 0) {
 70         printf("listen error\n");
 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]\n", 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\n", 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\n");
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\n");
107         return;
108     }
109     // too much connections
110     if (client_sd > MAX_CONNECTIONS) {
111         printf("fd too large[%d]\n", 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]\n", client_sd);
118         return;
119     }
120 
121     printf("client connected\n");
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\n");
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\n");
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\n");
147         return;
148     }
149 
150     if (read == 0) {
151         printf("client disconnected.\n");
152 
153         if (libevlist[watcher->fd] == NULL) {
154             printf("the fd already freed[%d]\n", watcher->fd);
155         }
156         else {
157             printf("fd:%d will be closed!\n",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\n",watcher->fd, buffer);
167         if(memcmp(buffer,"quit",strlen("quit")) == 0)
168         {
169             printf("recv quit cmd,fd:%d will be closed!\n",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 }

 

posted @ 2016-03-31 14:54  你且浅笑相安  阅读(3741)  评论(0编辑  收藏  举报