zoukankan      html  css  js  c++  java
  • Libevent例子(一)

    服务器端

    #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 = sizeof(client);
        sockfd = accept(fd, (struct sockaddr *) &client, &len);
        evutil_make_socket_nonblocking(sockfd);
        printf("accept a client %d
    ", sockfd);
        struct event_base *base = (struct 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] = '';
        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
    ");
        }
        else if (event & BEV_EVENT_ERROR) {
            printf("some other error
    ");
        }
        //这将自动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) {
            printf("please input 2 parameter
    ");
            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
    ");
        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 
    ");
        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] = '';
        printf("recv %s from server
    ", msg);
    }
    
    void event_cb(struct bufferevent *bev, short event, void *arg) {
    
        if (event & BEV_EVENT_EOF) {
            printf("connection closed
    ");
        } else if (event & BEV_EVENT_ERROR) {
            printf("some other error
    ");
        }
        //这将自动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;
    }
  • 相关阅读:
    我和LEGO Mindstroms NXT(1)
    [翻译]介绍Xbox LIVE社区游戏
    想做一个显示全国火车运行图的网站(1)想想
    [翻译]CCR and DSS Toolkit 2008 发布了
    我和LEGO Mindstroms NXT(2)
    [翻译]机器人游戏可以下载了!
    vs的form标签引起css走样问题
    做个md5查询站(1)从8年前说开去
    [翻译]Microsoft Robotics Developer Sutdio 2008 7月CTP发布了
    做个md5查询站(3)数据格式
  • 原文地址:https://www.cnblogs.com/milton/p/7837843.html
Copyright © 2011-2022 走看看