Libevent使用例子,從簡單到複雜,libevent例子

來源:互聯網
上載者:User

Libevent使用例子,從簡單到複雜,libevent例子


        轉載請註明出處:http://blog.csdn.net/luotuo44/article/details/39670221



        本文從簡單到複雜,展示怎麼使用Libevent。另外網上的很多例子都是只有伺服器端的,本文裡面用戶端和伺服器端都有。不說這麼多了,直接上代碼。

        


初等:用戶端代碼:

#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<errno.h>#include<unistd.h>#include<stdio.h>#include<string.h>#include<stdlib.h>#include<event.h>#include<event2/util.h>int tcp_connect_server(const char* server_ip, int port);void cmd_msg_cb(int fd, short events, void* arg);void socket_read_cb(int fd, short events, void *arg);int main(int argc, char** argv){    if( argc < 3 )    {        printf("please input 2 parameter\n");        return -1;    }    //兩個參數依次是伺服器端的IP地址、連接埠號碼    int sockfd = tcp_connect_server(argv[1], atoi(argv[2]));    if( sockfd == -1)    {        perror("tcp_connect error ");        return -1;    }    printf("connect to server successful\n");    struct event_base* base = event_base_new();    struct event *ev_sockfd = event_new(base, sockfd,                                        EV_READ | EV_PERSIST,                                        socket_read_cb, NULL);    event_add(ev_sockfd, NULL);    //監聽終端輸入事件    struct event* ev_cmd = event_new(base, STDIN_FILENO,                                      EV_READ | EV_PERSIST, cmd_msg_cb,                                      (void*)&sockfd);    event_add(ev_cmd, NULL);    event_base_dispatch(base);    printf("finished \n");    return 0;}void cmd_msg_cb(int fd, short events, void* arg){    char msg[1024];    int ret = read(fd, msg, sizeof(msg));    if( ret <= 0 )    {        perror("read fail ");        exit(1);    }    int sockfd = *((int*)arg);    //把終端的訊息發送給伺服器端    //為了簡單起見,不考慮寫一半資料的情況    write(sockfd, msg, ret);}void socket_read_cb(int fd, short events, void *arg){    char msg[1024];    //為了簡單起見,不考慮讀一半資料的情況    int len = read(fd, msg, sizeof(msg)-1);    if( len <= 0 )    {        perror("read fail ");        exit(1);    }    msg[len] = '\0';    printf("recv %s from server\n", msg);}typedef struct sockaddr SA;int tcp_connect_server(const char* server_ip, int port){    int sockfd, status, save_errno;    struct sockaddr_in server_addr;    memset(&server_addr, 0, sizeof(server_addr) );    server_addr.sin_family = AF_INET;    server_addr.sin_port = htons(port);    status = inet_aton(server_ip, &server_addr.sin_addr);    if( status == 0 ) //the server_ip is not valid value    {        errno = EINVAL;        return -1;    }    sockfd = ::socket(PF_INET, SOCK_STREAM, 0);    if( sockfd == -1 )        return sockfd;    status = ::connect(sockfd, (SA*)&server_addr, sizeof(server_addr) );    if( status == -1 )    {        save_errno = errno;        ::close(sockfd);        errno = save_errno; //the close may be error        return -1;    }    evutil_make_socket_nonblocking(sockfd);    return sockfd;}


伺服器端代碼:

#include<stdio.h>#include<string.h>#include<errno.h>#include<unistd.h>#include<event.h>void accept_cb(int fd, short events, void* arg);void socket_read_cb(int fd, short events, void *arg);int tcp_server_init(int port, int listen_num);int main(int argc, char** argv){    int listener = tcp_server_init(9999, 10);    if( listener == -1 )    {        perror(" tcp_server_init error ");        return -1;    }    struct event_base* base = event_base_new();    //添加監聽用戶端請求串連事件    struct event* ev_listen = event_new(base, listener, EV_READ | EV_PERSIST,                                        accept_cb, base);    event_add(ev_listen, NULL);    event_base_dispatch(base);    return 0;}void accept_cb(int fd, short events, void* arg){    evutil_socket_t sockfd;    struct sockaddr_in client;    socklen_t len;    sockfd = ::accept(fd, (struct sockaddr*)&client, &len );    evutil_make_socket_nonblocking(sockfd);    printf("accept a client %d\n", sockfd);    struct event_base* base = (event_base*)arg;    //僅僅是為了動態建立一個event結構體    struct event *ev = event_new(NULL, -1, 0, NULL, NULL);    //將動態建立的結構體作為event的回調參數    event_assign(ev, base, sockfd, EV_READ | EV_PERSIST,                 socket_read_cb, (void*)ev);    event_add(ev, NULL);}void socket_read_cb(int fd, short events, void *arg){    char msg[4096];    struct event *ev = (struct event*)arg;    int len = read(fd, msg, sizeof(msg) - 1);    if( len <= 0 )    {        printf("some error happen when read\n");        close(event_get_fd(ev));        event_free(ev);        return ;    }    msg[len] = '\0';    printf("recv the client msg: %s", msg);    char reply_msg[4096] = "I have recvieced the msg: ";    strcat(reply_msg + strlen(reply_msg), msg);    write(fd, reply_msg, strlen(reply_msg) );}typedef struct sockaddr SA;int tcp_server_init(int port, int listen_num){    int errno_save;    evutil_socket_t listener;    listener = ::socket(AF_INET, SOCK_STREAM, 0);    if( listener == -1 )        return -1;    //允許多次綁定同一個地址。要用在socket和bind之間    evutil_make_listen_socket_reuseable(listener);    struct sockaddr_in sin;    sin.sin_family = AF_INET;    sin.sin_addr.s_addr = 0;    sin.sin_port = htons(port);    if( ::bind(listener, (SA*)&sin, sizeof(sin)) < 0 )        goto error;    if( ::listen(listener, listen_num) < 0)        goto error;    //跨平台統一介面,將通訊端設定為非阻塞狀態    evutil_make_socket_nonblocking(listener);    return listener;    error:        errno_save = errno;        evutil_closesocket(listener);        errno = errno_save;        return -1;}




中等:用戶端代碼:

#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<errno.h>#include<unistd.h>#include<stdio.h>#include<string.h>#include<stdlib.h>#include<event.h>#include<event2/bufferevent.h>#include<event2/buffer.h>#include<event2/util.h>int tcp_connect_server(const char* server_ip, int port);void cmd_msg_cb(int fd, short events, void* arg);void server_msg_cb(struct bufferevent* bev, void* arg);void event_cb(struct bufferevent *bev, short event, void *arg);int main(int argc, char** argv){    if( argc < 3 )    {        printf("please input 2 parameter\n");        return -1;    }    //兩個參數依次是伺服器端的IP地址、連接埠號碼    int sockfd = tcp_connect_server(argv[1], atoi(argv[2]));    if( sockfd == -1)    {        perror("tcp_connect error ");        return -1;    }    printf("connect to server successful\n");    struct event_base* base = event_base_new();    struct bufferevent* bev = bufferevent_socket_new(base, sockfd,                                                     BEV_OPT_CLOSE_ON_FREE);    //監聽終端輸入事件    struct event* ev_cmd = event_new(base, STDIN_FILENO,                                      EV_READ | EV_PERSIST, cmd_msg_cb,                                      (void*)bev);    event_add(ev_cmd, NULL);    //當socket關閉時會用到回調參數    bufferevent_setcb(bev, server_msg_cb, NULL, event_cb, (void*)ev_cmd);    bufferevent_enable(bev, EV_READ | EV_PERSIST);    event_base_dispatch(base);    printf("finished \n");    return 0;}void cmd_msg_cb(int fd, short events, void* arg){    char msg[1024];    int ret = read(fd, msg, sizeof(msg));    if( ret < 0 )    {        perror("read fail ");        exit(1);    }    struct bufferevent* bev = (struct bufferevent*)arg;    //把終端的訊息發送給伺服器端    bufferevent_write(bev, msg, ret);}void server_msg_cb(struct bufferevent* bev, void* arg){    char msg[1024];    size_t len = bufferevent_read(bev, msg, sizeof(msg));    msg[len] = '\0';    printf("recv %s from server\n", msg);}void event_cb(struct bufferevent *bev, short event, void *arg){    if (event & BEV_EVENT_EOF)        printf("connection closed\n");    else if (event & BEV_EVENT_ERROR)        printf("some other error\n");    //這將自動close通訊端和free讀寫緩衝區    bufferevent_free(bev);    struct event *ev = (struct event*)arg;    //因為socket已經沒有,所以這個event也沒有存在的必要了    event_free(ev);}typedef struct sockaddr SA;int tcp_connect_server(const char* server_ip, int port){    int sockfd, status, save_errno;    struct sockaddr_in server_addr;    memset(&server_addr, 0, sizeof(server_addr) );    server_addr.sin_family = AF_INET;    server_addr.sin_port = htons(port);    status = inet_aton(server_ip, &server_addr.sin_addr);    if( status == 0 ) //the server_ip is not valid value    {        errno = EINVAL;        return -1;    }    sockfd = ::socket(PF_INET, SOCK_STREAM, 0);    if( sockfd == -1 )        return sockfd;    status = ::connect(sockfd, (SA*)&server_addr, sizeof(server_addr) );    if( status == -1 )    {        save_errno = errno;        ::close(sockfd);        errno = save_errno; //the close may be error        return -1;    }    evutil_make_socket_nonblocking(sockfd);    return sockfd;}



伺服器端代碼:

#include<stdio.h>#include<string.h>#include<errno.h>#include<event.h>#include<event2/bufferevent.h>void accept_cb(int fd, short events, void* arg);void socket_read_cb(bufferevent* bev, void* arg);void event_cb(struct bufferevent *bev, short event, void *arg);int tcp_server_init(int port, int listen_num);int main(int argc, char** argv){    int listener = tcp_server_init(9999, 10);    if( listener == -1 )    {        perror(" tcp_server_init error ");        return -1;    }    struct event_base* base = event_base_new();    //添加監聽用戶端請求串連事件    struct event* ev_listen = event_new(base, listener, EV_READ | EV_PERSIST,                                        accept_cb, base);    event_add(ev_listen, NULL);    event_base_dispatch(base);    event_base_free(base);    return 0;}void accept_cb(int fd, short events, void* arg){    evutil_socket_t sockfd;    struct sockaddr_in client;    socklen_t len;    sockfd = ::accept(fd, (struct sockaddr*)&client, &len );    evutil_make_socket_nonblocking(sockfd);    printf("accept a client %d\n", sockfd);    struct event_base* base = (event_base*)arg;    bufferevent* bev = bufferevent_socket_new(base, sockfd, BEV_OPT_CLOSE_ON_FREE);    bufferevent_setcb(bev, socket_read_cb, NULL, event_cb, arg);    bufferevent_enable(bev, EV_READ | EV_PERSIST);}void socket_read_cb(bufferevent* bev, void* arg){    char msg[4096];    size_t len = bufferevent_read(bev, msg, sizeof(msg));    msg[len] = '\0';    printf("recv the client msg: %s", msg);    char reply_msg[4096] = "I have recvieced the msg: ";    strcat(reply_msg + strlen(reply_msg), msg);    bufferevent_write(bev, reply_msg, strlen(reply_msg));}void event_cb(struct bufferevent *bev, short event, void *arg){    if (event & BEV_EVENT_EOF)        printf("connection closed\n");    else if (event & BEV_EVENT_ERROR)        printf("some other error\n");    //這將自動close通訊端和free讀寫緩衝區    bufferevent_free(bev);}typedef struct sockaddr SA;int tcp_server_init(int port, int listen_num){    int errno_save;    evutil_socket_t listener;    listener = ::socket(AF_INET, SOCK_STREAM, 0);    if( listener == -1 )        return -1;    //允許多次綁定同一個地址。要用在socket和bind之間    evutil_make_listen_socket_reuseable(listener);    struct sockaddr_in sin;    sin.sin_family = AF_INET;    sin.sin_addr.s_addr = 0;    sin.sin_port = htons(port);    if( ::bind(listener, (SA*)&sin, sizeof(sin)) < 0 )        goto error;    if( ::listen(listener, listen_num) < 0)        goto error;    //跨平台統一介面,將通訊端設定為非阻塞狀態    evutil_make_socket_nonblocking(listener);    return listener;    error:        errno_save = errno;        evutil_closesocket(listener);        errno = errno_save;        return -1;}



高等:用戶端代碼:

#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<errno.h>#include<unistd.h>#include<stdio.h>#include<string.h>#include<stdlib.h>#include<event.h>#include<event2/bufferevent.h>#include<event2/buffer.h>#include<event2/util.h>int tcp_connect_server(const char* server_ip, int port);void cmd_msg_cb(int fd, short events, void* arg);void server_msg_cb(struct bufferevent* bev, void* arg);void event_cb(struct bufferevent *bev, short event, void *arg);int main(int argc, char** argv){    if( argc < 3 )    {        //兩個參數依次是伺服器端的IP地址、連接埠號碼        printf("please input 2 parameter\n");        return -1;    }    struct event_base *base = event_base_new();    struct bufferevent* bev = bufferevent_socket_new(base, -1,                                                     BEV_OPT_CLOSE_ON_FREE);    //監聽終端輸入事件    struct event* ev_cmd = event_new(base, STDIN_FILENO,                                     EV_READ | EV_PERSIST,                                     cmd_msg_cb, (void*)bev);    event_add(ev_cmd, NULL);    struct sockaddr_in server_addr;    memset(&server_addr, 0, sizeof(server_addr) );    server_addr.sin_family = AF_INET;    server_addr.sin_port = htons(atoi(argv[2]));    inet_aton(argv[1], &server_addr.sin_addr);    bufferevent_socket_connect(bev, (struct sockaddr *)&server_addr,                               sizeof(server_addr));    bufferevent_setcb(bev, server_msg_cb, NULL, event_cb, (void*)ev_cmd);    bufferevent_enable(bev, EV_READ | EV_PERSIST);    event_base_dispatch(base);    printf("finished \n");    return 0;}void cmd_msg_cb(int fd, short events, void* arg){    char msg[1024];    int ret = read(fd, msg, sizeof(msg));    if( ret < 0 )    {        perror("read fail ");        exit(1);    }    struct bufferevent* bev = (struct bufferevent*)arg;    //把終端的訊息發送給伺服器端    bufferevent_write(bev, msg, ret);}void server_msg_cb(struct bufferevent* bev, void* arg){    char msg[1024];    size_t len = bufferevent_read(bev, msg, sizeof(msg));    msg[len] = '\0';    printf("recv %s from server\n", msg);}void event_cb(struct bufferevent *bev, short event, void *arg){    if (event & BEV_EVENT_EOF)        printf("connection closed\n");    else if (event & BEV_EVENT_ERROR)        printf("some other error\n");    else if( event & BEV_EVENT_CONNECTED)    {        printf("the client has connected to server\n");        return ;    }    //這將自動close通訊端和free讀寫緩衝區    bufferevent_free(bev);    struct event *ev = (struct event*)arg;    event_free(ev);}



伺服器端代碼:

#include<netinet/in.h>#include<sys/socket.h>#include<unistd.h>#include<stdio.h>#include<string.h>#include<event.h>#include<listener.h>#include<bufferevent.h>#include<thread.h>void listener_cb(evconnlistener *listener, evutil_socket_t fd,                 struct sockaddr *sock, int socklen, void *arg);void socket_read_cb(bufferevent *bev, void *arg);void socket_event_cb(bufferevent *bev, short events, void *arg);int main(){    //evthread_use_pthreads();//enable threads    struct sockaddr_in sin;    memset(&sin, 0, sizeof(struct sockaddr_in));    sin.sin_family = AF_INET;    sin.sin_port = htons(9999);    event_base *base = event_base_new();    evconnlistener *listener            = evconnlistener_new_bind(base, listener_cb, base,                                      LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,                                      10, (struct sockaddr*)&sin,                                      sizeof(struct sockaddr_in));    event_base_dispatch(base);    evconnlistener_free(listener);    event_base_free(base);    return 0;}//一個新用戶端串連上伺服器了void listener_cb(evconnlistener *listener, evutil_socket_t fd,                 struct sockaddr *sock, int socklen, void *arg){    printf("accept a client %d\n", fd);    event_base *base = (event_base*)arg;    //為這個用戶端分配一個bufferevent    bufferevent *bev =  bufferevent_socket_new(base, fd,                                               BEV_OPT_CLOSE_ON_FREE);    bufferevent_setcb(bev, socket_read_cb, NULL, socket_event_cb, NULL);    bufferevent_enable(bev, EV_READ | EV_PERSIST);}void socket_read_cb(bufferevent *bev, void *arg){    char msg[4096];    size_t len = bufferevent_read(bev, msg, sizeof(msg)-1 );    msg[len] = '\0';    printf("server read the data %s\n", msg);    char reply[] = "I has read your data";    bufferevent_write(bev, reply, strlen(reply) );}void socket_event_cb(bufferevent *bev, short events, void *arg){    if (events & BEV_EVENT_EOF)        printf("connection closed\n");    else if (events & BEV_EVENT_ERROR)        printf("some other error\n");    //這將自動close通訊端和free讀寫緩衝區    bufferevent_free(bev);}







為何那些理論性東西(專用名詞,術語等等)其實都是生活很簡單的例子,喜歡把很簡單的東西說的很複雜?

解釋不是定義,定義才是科學的界說。另外,任何專業的發展都有技能同用語的區別,用語越來越複雜,是為了建立一種membership的關係,不懂此言,不在此圈,一邊獃著去的意思!
 
複雜的事情怎簡單做,簡單的事情怎複雜做?最好有例子

上學拿文憑很複雜,其實花錢買個偽造的證件唄.性很簡單,其實你得花心血找到對手
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.