zoukankan      html  css  js  c++  java
  • Linux IO模式及 select、poll、epoll详解及源码(转)

    原文:https://segmentfault.com/a/1190000003063859

    我只摘取了其中的epoll代码示例,服务端代码

    
    
    #define IPADDRESS   "127.0.0.1"
    #define PORT        8787
    #define MAXSIZE     1024
    #define LISTENQ     5
    #define FDSIZE      1000
    #define EPOLLEVENTS 100
    
    listenfd = socket_bind(IPADDRESS,PORT);
    
    struct epoll_event events[EPOLLEVENTS];
    
    //创建一个描述符
    epollfd = epoll_create(FDSIZE);
    
    //添加监听描述符事件
    add_event(epollfd,listenfd,EPOLLIN);
    
    //循环等待
    for ( ; ; ){
        //该函数返回已经准备好的描述符事件数目
        ret = epoll_wait(epollfd,events,EPOLLEVENTS,-1);
        //处理接收到的连接
        handle_events(epollfd,events,ret,listenfd,buf);
    }
    
    //事件处理函数
    static void handle_events(int epollfd,struct epoll_event *events,int num,int listenfd,char *buf)
    {
         int i;
         int fd;
         //进行遍历;这里只要遍历已经准备好的io事件。num并不是当初epoll_create时的FDSIZE。
         for (i = 0;i < num;i++)
         {
             fd = events[i].data.fd;
            //根据描述符的类型和事件类型进行处理
             if ((fd == listenfd) &&(events[i].events & EPOLLIN))
                handle_accpet(epollfd,listenfd);
             else if (events[i].events & EPOLLIN)
                do_read(epollfd,fd,buf);
             else if (events[i].events & EPOLLOUT)
                do_write(epollfd,fd,buf);
         }
    }
    
    //添加事件
    static 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);
    }
    
    //处理接收到的连接。将文件描述符添加到epoll监控队列
    static void handle_accpet(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);     
         } 
    }
    
    //读处理
    static void do_read(int epollfd,int fd,char *buf){
        int nread;
        nread = read(fd,buf,MAXSIZE);
        if (nread == -1)     {         
            perror("read error:");         
            close(fd); //记住close fd        
            delete_event(epollfd,fd,EPOLLIN); //删除监听 
        }
        else if (nread == 0)     {         
            fprintf(stderr,"client close.
    ");
            close(fd); //记住close fd       
            delete_event(epollfd,fd,EPOLLIN); //删除监听 
        }     
        else {         
            printf("read message is : %s",buf);        
            //修改描述符对应的事件,由读改为写         
            modify_event(epollfd,fd,EPOLLOUT);     
        } 
    }
    
    //写处理
    static void do_write(int epollfd,int fd,char *buf) {     
        int nwrite;     
        nwrite = write(fd,buf,strlen(buf));     
        if (nwrite == -1){         
            perror("write error:");        
            close(fd);   //记住close fd       
            delete_event(epollfd,fd,EPOLLOUT);  //删除监听    
        }else{
            modify_event(epollfd,fd,EPOLLIN); 
        }    
        memset(buf,0,MAXSIZE); 
    }
    
    //删除事件
    static 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);
    }
    
    //修改事件
    static 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);
    }
    
    //注:另外一端我就省了
  • 相关阅读:
    ECharts 3 -- gauge表盘的配置项
    8 -- 深入使用Spring -- 1...4 属性占位符配置器
    8 -- 深入使用Spring -- 1...两种后处理器
    window.location.href
    8 -- 深入使用Spring -- 1...3 容器后处理器
    8 -- 深入使用Spring -- 1...2 Bean后处理器的用处
    8 -- 深入使用Spring -- 1...1Bean后处理器
    8 -- 深入使用Spring -- 0...
    Java NIO原理 图文分析及代码实现
    Java NIO系列教程(十二) Java NIO与IO
  • 原文地址:https://www.cnblogs.com/ajianbeyourself/p/5860020.html
Copyright © 2011-2022 走看看