zoukankan      html  css  js  c++  java
  • unix网络编程 str_cli epoll 非阻塞版本

    unix网络编程 str_cli epoll 非阻塞版本

    unix网络编程str_cli使用epoll实现讲了使用epoll配合阻塞io来实现str_cli,这个版本是配合非阻塞io.
    可以看到采用非阻塞io以后复杂度大大提升了. 这个版本是在原书select版本基础之上修改而来,可以看出epoll又比select版本复杂了很多,每次都需要调用epoll_ctl三次,效率肯定比select还低.

    存在一个问题!!就是epoll_wait对于重定向的stdin,始终阻塞,不晓得什么原因,以后再研究吧!

    因为不能重定向stdin所以也不能测试性能,只能说是可以工作.

    /* include nonb1 */
    #include    "../lib/unp.h"
    #include <sys/epoll.h>
    //epoll 非阻塞io, 采用了非阻塞io以后性能得到大幅提升,但是复杂度也飞速提升。
    
    //确保events有足够的空间,这里足够了
    //添加一个事件到队列中,可能会改变数组中的epoll_event数量。
    static uint32_t addEvents(struct epoll_event * events,uint32_t nfds,int fd,uint32_t event){
        int i=0;
        for(i=0;i<nfds;i++){
            if(events[i].data.fd==fd){
                events[i].events|=event;
            }
        }
        if(i==nfds){
            events[i].data.fd=fd;
            events[i].events=event;
            nfds++;
        }
        return nfds;
    }
    #define VOL2
    void str_cli(FILE *fp, int sockfd)
    {
        int         val,stdineof=0;
        ssize_t     n, nwritten;
        char        to[MAXLINE], fr[MAXLINE];
        char        *toiptr, *tooptr, *friptr, *froptr;
        struct epoll_event event;
        struct epoll_event events[20];
        int i,efd,nfds;
        int noevent=0;
    
        val = Fcntl(sockfd, F_GETFL, 0);
        Fcntl(sockfd, F_SETFL, val | O_NONBLOCK);
    
        val = Fcntl(STDIN_FILENO, F_GETFL, 0);
        Fcntl(STDIN_FILENO, F_SETFL, val | O_NONBLOCK);
    
        val = Fcntl(STDOUT_FILENO, F_GETFL, 0);
        Fcntl(STDOUT_FILENO, F_SETFL, val | O_NONBLOCK);
    
        toiptr = tooptr = to;   /* initialize buffer pointers */
        friptr = froptr = fr;
        stdineof = 0;
    
        efd = epoll_create (10);
        if(efd<0){
            err_sys("epoll create failed");
        }
    
    
        event.data.fd=fileno(fp);
        event.events=EPOLLIN;
        epoll_ctl(efd,EPOLL_CTL_ADD,fileno(fp),&event);
    
        event.data.fd=sockfd;
        event.events=EPOLLIN;
        epoll_ctl(efd,EPOLL_CTL_ADD,sockfd,&event);
    
        event.data.fd=STDOUT_FILENO;
        event.events=EPOLLOUT;
        epoll_ctl(efd,EPOLL_CTL_ADD,STDOUT_FILENO,&event);
    
    
        for ( ; ; ) {
    
            event.data.fd = fileno(fp);
            event.events = 0;
            //fprintf(stderr, "tooptr=0x%x,toiptr=0x%x,froptr=0x%x,friptr=0x%x 
    ", tooptr, toiptr, froptr, friptr);
            if (stdineof == 0 && toiptr < &to[MAXLINE]) //并不能确定在不在里面,多做一次不是坏事
            {
                event.events = EPOLLIN;
                epoll_ctl(efd, EPOLL_CTL_MOD, fileno(fp), &event); //read from stdin
            }
            else
                epoll_ctl(efd, EPOLL_CTL_MOD, fileno(fp), &event);
    
    
            event.data.fd = sockfd;
            event.events = 0;
            if (friptr < &fr[MAXLINE])
                event.events |= EPOLLIN;            /* read from socket */
            if (tooptr != toiptr)
                event.events |= EPOLLOUT;            /* data to write to socket */
            epoll_ctl(efd, EPOLL_CTL_MOD, sockfd, &event);
    
            event.data.fd = STDOUT_FILENO;
            event.events = 0;
            if (froptr != friptr) {
                event.events = EPOLLOUT;
                epoll_ctl(efd, EPOLL_CTL_MOD, STDOUT_FILENO, &event);    /* data to write to stdout */
            }
            else {
                epoll_ctl(efd, EPOLL_CTL_MOD, STDOUT_FILENO, &event);
            }
    
            nfds = epoll_wait(efd, events, sizeof(events) / sizeof(struct epoll_event), -1);
            //fprintf(stderr, "nfds return:%d, %d,0x%x,sockfd=%d
    ", nfds, events[0].data.fd, events[0].events, sockfd);
            startloop:
            for (i = 0; i < nfds; i++) {
                if (events[i].data.fd == STDIN_FILENO && events[i].events != 0) {
                    events[i].events = 0; //清除处理过的事件
                    if ((n = read(STDIN_FILENO, toiptr, &to[MAXLINE] - toiptr)) < 0) {
                        if (errno != EWOULDBLOCK)
                            err_sys("read error on stdin");
    
                    } else if (n == 0) {
    #ifdef    VOL2
                        fprintf(stderr, "%s: EOF on stdin
    ", gf_time());
    #endif
                        stdineof = 1;            /* all done with stdin */
                        if (tooptr == toiptr)
                            Shutdown(sockfd, SHUT_WR);/* send FIN */
    
                    } else {
    #ifdef    VOL2
                        fprintf(stderr, "%s: read %d bytes from stdin
    ", gf_time(), n);
    #endif
                        toiptr += n;            /* # just read */
                        int ret2=addEvents(events, nfds, sockfd, EPOLLOUT);
                        if(ret2!=nfds){
                            nfds=ret2;
                            goto startloop;
                        }
                    }
                }
    
                if (events[i].data.fd == sockfd && events[i].events != 0) {
                    if (events[i].events & EPOLLIN) {
                        printf("read socket
    ");
                        if ((n = read(sockfd, friptr, &fr[MAXLINE] - friptr)) < 0) {
                            printf("read socket error");
                            if (errno != EWOULDBLOCK)
                                err_sys("read error on socket");
    
                        } else if (n == 0) {
    #ifdef    VOL2
                            fprintf(stderr, "%s: EOF on socket
    ", gf_time());
    #endif
                            if (stdineof)
                                return;        /* normal termination */
                            else
                                err_quit("str_cli: server terminated prematurely");
    
                        } else {
    #ifdef    VOL2
                            fprintf(stderr, "%s: read %d bytes from socket
    ",
                                    gf_time(), n);
    #endif
                            friptr += n;        /* # just read */
                            int ret2 = addEvents(events, nfds, STDOUT_FILENO, EPOLLOUT);/* try and write for next loop */
                            if(ret2!=nfds){
                                nfds=ret2;
                                events[i].events&=~EPOLLIN; //清除已经处理过的in事件
                                goto startloop;
                            }
                        }
                    }
                    if (events[i].events & EPOLLOUT) {
                        if ((n = toiptr - tooptr) > 0) {
                            if ((nwritten = write(sockfd, tooptr, n)) < 0) {
                                if (errno != EWOULDBLOCK)
                                    err_sys("write error to socket");
    
                            } else {
    #ifdef    VOL2
                                fprintf(stderr, "%s: wrote %d bytes to socket
    ",
                                        gf_time(), nwritten);
    #endif
                                tooptr += nwritten;    /* # just written */
                                if (tooptr == toiptr) {
                                    toiptr = tooptr = to;    /* back to beginning of buffer */
                                    if (stdineof)
                                        Shutdown(sockfd, SHUT_WR);    /* send FIN */
                                }
                            }
                        }
                    }
                    events[i].events = 0; //清除处理过的事件
                }
    
                if (events[i].data.fd == STDOUT_FILENO) {
                    if ((n = friptr - froptr) > 0) {
                        if ((nwritten = write(STDOUT_FILENO, froptr, n)) < 0) {
                            if (errno != EWOULDBLOCK)
                                err_sys("write error to stdout");
    
                        } else {
    #ifdef    VOL2
                            fprintf(stderr, "%s: wrote %d bytes to stdout
    ",
                                    gf_time(), nwritten);
    #endif
                            froptr += nwritten;        /* # just written */
                            if (froptr == friptr)
                                froptr = friptr = fr;    /* back to beginning of buffer */
                        }
                    }
    
                }
            }
        }
    }
    
  • 相关阅读:
    mybatis3.0-[topic10-14] -全局配置文件_plugins插件简介/ typeHandlers_类型处理器简介 /enviroments_运行环境 /多数据库支持/mappers_sql映射注册
    _MyBatis3-topic06.07.08.09_ 全局配置文件_引入dtd约束(xml提示)/ 引入properties引用/ 配置驼峰命名自动匹配 /typeAliases起别名.批量起别名
    MyBatis3-topic04,05 -接口式编程
    JDBC终章- 使用 DBUtils实现增删查改- C3P0Utils数据源/QueryRunner runner连接数据源并执行sql
    [课本10.1.4]JDBC数据库连接池- C3P0数据源--通过构造方法创建数据源对象--通过配置文件创建数据源对象[推荐]
    JDBC课程5--利用反射及JDBC元数据(ResultSetMetaData)编写通用的查询方法
    JDBC课程4--使用PreparedStatement进行增删查改--封装进JDBCTools的功能中;模拟SQL注入 ; sql的date()传入参数值格式!
    本周进度总结
    本周进度总结
    大道至简读后感
  • 原文地址:https://www.cnblogs.com/baizx/p/5184658.html
Copyright © 2011-2022 走看看