zoukankan      html  css  js  c++  java
  • epoll案例

    epoll 案例

    分析见下回分解

    server.cpp

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <sys/epoll.h>
    #include <unistd.h>
    #include <sys/types.h>
    
    #define IPADDRESS   "127.0.0.1"
    #define PORT        6666
    #define MAXSIZE     1024
    #define LISTENQ     5
    #define FDSIZE      1000
    #define EPOLLEVENTS 100
    
    // 创建套接字并进行绑定
    int socket_bind(const char* ip, int port);
    
    // IO多路复用 epoll
    void do_epoll(int listenfd);
    
    // 处理事件函数
    void handle_events(int epollfd, struct epoll_event *events, int num,
            int listenfd, char* buf);
    
    // 处理接收到的连接
    void handle_accept(int epollfd, int listenfd);
    
    // 读处理
    void do_read(int epollfd, int fd, char* buf);
    
    // 写处理
    void do_write(int epollfd, int fd, char *buf);
    
    // 添加事件
    void add_event(int epollfd, int fd, int state);
    
    // 修改事件
    void modify_event(int epollfd, int fd, int state);
    
    // 删除事件
    void delete_event(int epollfd, int fd, int state);
    
    int main(int argc, char *argv[])
    {
        int listenfd = 0;
        listenfd = socket_bind(IPADDRESS, PORT);
        listen(listenfd, LISTENQ);
        do_epoll(listenfd);
        return 0;
    }
    
    int socket_bind(const char* ip, int port)
    {
        int listenfd = 0;
        struct sockaddr_in servaddr;
        listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if(listenfd == -1) {
            perror("socket error");
            exit(1);
        }
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        inet_pton(AF_INET, ip, &servaddr.sin_addr);
        servaddr.sin_port = htons(port);
    
        if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) {
            perror("bind error: ");
            exit(1);
        }
        return listenfd;
    }
    
    void do_epoll(int listenfd) {
        int epollfd;
        struct epoll_event events[EPOLLEVENTS];
        int ret;
        char buf[MAXSIZE];
        memset(buf, 0, MAXSIZE);
        // 创建一个描述符
        epollfd =  epoll_create(FDSIZE);
        // 添加监听描述事件
        add_event(epollfd, listenfd, EPOLLIN);
        while(true) {
            // 获取已经准备好的描述事件
            ret = epoll_wait(epollfd, events, EPOLLEVENTS, -1);
            handle_events(epollfd, events, ret, listenfd, buf);
        }
        close(epollfd);
    }
    
    void handle_events(int epollfd, struct epoll_event *events, int num,
                       int listenfd, char* buf) {
        for(int i = 0; i < num; i++ ) {
            int fd = events[i].data.fd;
            // 根据描述符的类型和事件类型进行处理
            if((fd == listenfd) && (events[i].events & EPOLLIN)) {
                handle_accept(epollfd, listenfd);
            } else if(events[i].events & EPOLLIN) {
                do_read(epollfd, fd, buf);
            } else if(events[i].events & EPOLLOUT) {
                do_write(epollfd, fd, buf);
            }
        }
    }
    
    void handle_accept(int epollfd, int listenfd) {
        int clifd;
        struct sockaddr_in cliaddr;
        socklen_t cliaddrlen;
        clifd = accept(listenfd, (struct sockaddr*)&cliaddr, &cliaddrlen);
        if(clifd == -1) {
            perror("accpet error:");
        } else {
            printf("accept a new client: %s : %d
    ", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
            // 添加一个客户端描述符和事件
            add_event(epollfd, clifd, EPOLLIN);
        }
    }
    
    void do_read(int epollfd, int fd, char* buf) {
        int nread = read(fd, buf, MAXSIZE);
        if(nread == -1) {
            perror("read error:");
            close(fd);
            delete_event(epollfd, fd, EPOLLIN);
        }
        else if(nread == 0) {
            fprintf(stderr, "client close.
    ");
            close(fd);
            delete_event(epollfd, fd, EPOLLIN);
        } else {
            printf("read message is: %s 
    ", buf);
            modify_event(epollfd, fd, EPOLLOUT);
        }
    }
    
    void do_write(int epollfd, int fd, char* buf) {
        int nwrite = write(fd, buf, strlen(buf));
        if(nwrite == -1) {
            perror("write error: ");
            close(fd);
            delete_event(epollfd, fd, EPOLLOUT);
        } else {
            modify_event(epollfd, fd, EPOLLIN);
        }
        memset(buf, 0, MAXSIZE);
    }
    
    void add_event(int epollfd, int fd, int state) {
        struct epoll_event ev;
        ev.events = state;
        ev.data.fd = fd;
        epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);
    }
    
    void delete_event(int epollfd, int fd, int state) {
        struct epoll_event ev;
        ev.events = state;
        ev.data.fd = fd;
        epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &ev);
    }
    
    void modify_event(int epollfd, int fd, int state) {
        struct epoll_event ev;
        ev.events = state;
        ev.data.fd = fd;
        epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &ev);
    }
    

    client.cpp

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <time.h>
    
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <sys/epoll.h>
    #include <unistd.h>
    #include <sys/types.h>
    
    #define IPADDRESS   "127.0.0.1"
    #define SERV_PORT        6666
    #define MAXSIZE     1024
    #define FDSIZE      1024
    #define EPOLLEVENTS 20
    
    int count = 0;
    
    void handle_connection(int sockfd);
    
    // 处理事件函数
    void handle_events(int epollfd, struct epoll_event *events, int num,
                       int sockfd, char* buf);
    
    // 读处理
    void do_read(int epollfd, int fd, int sockfd, char* buf);
    
    // 写处理
    void do_write(int epollfd, int fd, int sockfd, char* buf);
    
    // 添加事件
    void add_event(int epollfd, int fd, int state);
    
    // 修改事件
    void modify_event(int epollfd, int fd, int state);
    
    // 删除事件
    void delete_event(int epollfd, int fd, int state);
    
    int main(int argc, char *argv[])
    {
        int sockfd;
    
        struct sockaddr_in servaddr;
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(SERV_PORT);
        inet_pton(AF_INET, IPADDRESS, &servaddr.sin_addr);
        connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
        //处理连接
        handle_connection(sockfd);
        close(sockfd);
        return 0;
    }
    
    void handle_connection(int sockfd) {
        int epollfd;
        struct epoll_event events[EPOLLEVENTS];
        char buf[MAXSIZE];
    
        int ret;
        epollfd = epoll_create(FDSIZE);
        add_event(epollfd, STDIN_FILENO, EPOLLIN);
        while(1) {
            ret = epoll_wait(epollfd, events, EPOLLEVENTS, -1);
            handle_events(epollfd, events, ret, sockfd, buf);
        }
        close(epollfd);
    }
    
    void handle_events(int epollfd, struct epoll_event *events, int num,
                       int sockfd, char* buf) {
        for(int i = 0; i < num; i++ ) {
            int fd = events[i].data.fd;
            // 根据描述符的类型和事件类型进行处理
            if(events[i].events & EPOLLIN) {
                do_read(epollfd, fd, sockfd, buf);
            } else if(events[i].events & EPOLLOUT) {
                do_write(epollfd, fd, sockfd, buf);
            }
        }
    }
    
    void do_read(int epollfd, int fd, int sockfd, char* buf) {
        int nread = read(fd, buf, MAXSIZE);
        if(nread == -1) {
            perror("read error:");
            close(fd);
        }
        else if(nread == 0) {
            fprintf(stderr, "client close.
    ");
            close(fd);
        } else {
            if(fd == STDIN_FILENO) {
                add_event(epollfd, sockfd, EPOLLOUT);
            } else {
                delete_event(epollfd, sockfd, EPOLLIN);
                add_event(epollfd, STDOUT_FILENO, EPOLLOUT);
            }
        }
    }
    
    void do_write(int epollfd, int fd, int sockfd, char* buf) {
        int nwrite = write(fd, buf, strlen(buf));
        char tmp[105] = {0};
        snprintf(tmp, sizeof(tmp), "%s_%02d
    ", buf, count++);
        nwrite = write(fd, tmp, strlen(tmp));
        if(nwrite == -1) {
            perror("write error:");
            close(fd);
        } else {
            if(fd == STDOUT_FILENO) {
                delete_event(epollfd, fd, EPOLLOUT);
            } else {
                modify_event(epollfd, fd, EPOLLIN);
            }
        }
        memset(buf, 0, MAXSIZE);
    }
    
    void add_event(int epollfd, int fd, int state) {
        struct epoll_event ev;
        ev.events = state;
        ev.data.fd = fd;
        epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);
    }
    
    void delete_event(int epollfd, int fd, int state) {
        struct epoll_event ev;
        ev.events = state;
        ev.data.fd = fd;
        epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &ev);
    }
    
    void modify_event(int epollfd, int fd, int state) {
        struct epoll_event ev;
        ev.events = state;
        ev.data.fd = fd;
        epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &ev);
    }
    
  • 相关阅读:
    201771010128王玉兰《面向对象程序设计(Java)》第十三周学习总结
    201771010128王玉兰《面向对象程序设计(Java)》第十二周学习总结
    王玉兰201771010128《面向对象与程序设计(Java)》第十一周学习总结
    201771010128王玉兰《面向对象程序设计(Java)》第十周学习总结
    王玉兰201771010128《面象对象程序设计(Java)》第九周学习总结
    201771010128王玉兰《面向对象程序设计(Java)》第八周学习总结
    AI核心代码解题思路
    《2018面向对象程序设计(java)课程学习进度条》
    解决结束进程explorer.exe后出现蓝屏的办法
    201771010123-汪慧和 实验四 软件项目案例分析
  • 原文地址:https://www.cnblogs.com/Q1143316492/p/10476181.html
Copyright © 2011-2022 走看看