zoukankan      html  css  js  c++  java
  • 各I/O模型 对应Web服务应用模型(select,poll,epoll,kevent,"/dev/poll")

    一、利用select多路复用I/O的Web服务应用模型 

    /* 可读、可写、异常三种文件描述符集的申明和初始化。*/ 
    fd_set readfds, writefds, exceptionfds; 
    FD_ZERO(&readfds); 
    FD_ZERO(&writefds); 
    FD_ZERO(&exceptionfds); 
    
    int max_fd; 
    
    /* socket配置和监听。*/ 
    sock = socket(...); 
    bind(sock, ...); 
    listen(sock, ...); 
    
    /* 对socket描述符上发生关心的事件进行注册。*/ 
    FD_SET(&readfds, sock); 
    max_fd = sock; 
    
    while(1) { 
    int i; 
    fd_set r,w,e; 
    
    /* 为了重复使用readfds 、writefds、exceptionfds,将它们拷贝到临时变量内。*/ 
    memcpy(&r, &readfds, sizeof(fd_set)); 
    memcpy(&w, &writefds, sizeof(fd_set)); 
    memcpy(&e, &exceptionfds, sizeof(fd_set)); 
    
    /* 利用临时变量调用select()阻塞等待,等待时间为永远等待直到发生事件。*/ 
    select(max_fd + 1, &r, &w, &e, NULL); 
    
    /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/ 
    if(FD_ISSET(&r, sock)){ 
    new_sock = accept(sock, ...); 
    FD_SET(&readfds, new_sock); 
    FD_SET(&writefds, new_sock); 
    max_fd = MAX(max_fd, new_sock); 
    } 
    /* 对其它描述符发生的事件进行适当处理。描述符依次递增,最大值各系统有所不同(比如在作者系统上最大为1024),在linux可以用命令ulimit -a查看(用ulimit命令也对该值进行修改)。在freebsd下,用sysctl -a | grep kern.maxfilesperproc来查询和修改。*/ 
    for(i= sock+1; i <max_fd+1; ++i) { 
    if(FD_ISSET(&r, i)) 
    doReadAction(i); 
    if(FD_ISSET(&w, i)) 
    doWriteAction(i); 
    } 
    } 

    二、利用poll多路复用I/O的Web服务应用模型 

    /* 新建并初始化文件描述符集。*/ 
    struct pollfd fds[MAX_NUM_FDS]; 
    int max_fd; 
    
    /* socket配置和监听。*/ 
    sock = socket(...); 
    bind(sock, ...); 
    listen(sock, ...); 
    
    /* 对socket描述符上发生关心的事件进行注册。*/ 
    fds[0].fd = sock; 
    fds[0].events = POLLIN; 
    max_fd = 1; 
    
    while(1) { 
    int i; 
    
    /*调用poll()阻塞等待,等待时间为永远等待直到发生事件。*/ 
    poll(fds, max_fd, -1); 
    
    /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/ 
    if(fds[0].revents & POLLIN){ 
    new_sock = accept(sock, ...); 
    fds[max_fd].fd = new_sock; 
    fds[max_fd].events = POLLIN | POLLOUT; 
    ++ max_fd; 
    } 
    /* 对其它描述符发生的事件进行适当处理。*/ 
    for(i=1; i <max_fd+1; ++i) { 
    if(fds.revents & POLLIN) 
    doReadAction(i); 
    if(fds.revents & POLLOUT) 
    doWriteAction(i); 
    } 
    } 
    
    利用epoll多路复用I/O的Web服务应用模型 
    /* 新建并初始化文件描述符集。*/ 
    struct epoll_event ev; 
    struct epoll_event events[MAX_EVENTS]; 
    
    /* 创建epoll句柄。*/ 
    int epfd = epoll_create(MAX_EVENTS); 
    
    /* socket配置和监听。*/ 
    sock = socket(...); 
    bind(sock, ...); 
    listen(sock, ...); 
    
    /* 对socket描述符上发生关心的事件进行注册。*/ 
    ev.events = EPOLLIN; 
    ev.data.fd = sock; 
    epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev); 
    
    while(1) { 
    int i; 
    /*调用epoll_wait()阻塞等待,等待时间为永远等待直到发生事件。*/ 
    int n = epoll_wait(epfd, events, MAX_EVENTS, -1); 
    for(i=0; i <n; ++i) { 
    /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/ 
    if(events.data.fd == sock) { 
    if(events.events & POLLIN){ 
    new_sock = accept(sock, ...); 
    ev.events = EPOLLIN | POLLOUT; 
    ev.data.fd = new_sock; 
    epoll_ctl(epfd, EPOLL_CTL_ADD, new_sock, &ev); 
    } 
    }else{ 
    /* 对其它描述符发生的事件进行适当处理。*/ 
    if(events.events & POLLIN) 
    doReadAction(i); 
    if(events.events & POLLOUT) 
    doWriteAction(i); 
    } 
    } 
    } 

    三、利用kqueue多路复用I/O的Web服务应用模型

    /* 新建并初始化文件描述符集。*/ 
    struct kevent changelist[MAX_EVENTS]; 
    struct kevent eventlist[MAX_EVENTS]; 
    int count = 0; 
    
    /* 创建kqueue句柄。*/ 
    int kqfd = kqueue(); 
    
    /* socket配置和监听。*/ 
    sock = socket(...); 
    bind(sock, ...); 
    listen(sock, ...); 
    
    /* 对socket描述符上发生关心的事件进行注册。*/ 
    EV_SET(&changelist[0], sock, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, 
    0, 0, 0); 
    ++ count; 
    
    while(1) { 
    int i; 
    /*调用kevent()阻塞等待,等待时间为永远等待直到发生事件。*/ 
    int n = kevent(kqfd, changelist, count, eventlist, count, NULL); 
    for(i=0; i <n; ++i) { 
    /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/ 
    if(eventlist.ident == sock) { 
    new_sock = accept(sock, ...); 
    EV_SET(&changelist[count], new_sock, EVFILT_READ, 
    EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0); 
    ++ count; 
    }else{ 
    /* 对其它描述符发生的事件进行适当处理。*/ 
    doReadAction(i); 
    } 
    } 
    } 


    四、利用/dev/poll多路复用I/O的Web服务应用模型

    /* 新建并初始化文件描述符集。*/ 
    struct pollfd pfd; 
    struct pollfd pollfds[MAX_EVENTS]; 
    struct dvpoll dopoll; 
    int count = 0; 
    
    /* 打开/dev/poll设备,创建poll句柄。*/ 
    int dpfd = open("/dev/poll", O_RDWR); 
    
    /* socket配置和监听。*/ 
    sock = socket(...); 
    bind(sock, ...); 
    listen(sock, ...); 
    
    /* 对socket描述符上发生关心的事件进行注册。*/ 
    pfd.fd = sock; 
    pfd.events = EPOLLIN; 
    pfd.revents = 0; 
    write(dpfd, pfd, sizeof(pfd)); 
    ++ count; 
    
    while(1) { 
    int i; 
    /*调用ioctl()阻塞等待,等待时间为永远等待直到发生事件。*/ 
    dopoll.dp_timeout = -1; 
    dopoll.dp_nfds = count; 
    dopoll.dp_fds = &pollfds; 
    int n = ioctl(dpfd, DP_POLL, &dopoll); 
    for(i=0; i <n; ++i) { 
    /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/ 
    if(pollfds.fd == sock) { 
    if(pollfds.revents & POLLIN){ 
    new_sock = accept(sock, ...); 
    pfd.fd = new_sock; 
    pfd.events = EPOLLIN | POLLOUT; 
    pfd.revents = 0; 
    write(dpfd, pfd, sizeof(pfd)); 
    ++ count; 
    } 
    }else{ 
    /* 对其它描述符发生的事件进行适当处理。*/ 
    if(pollfds.revents & POLLIN) 
    doReadAction(i); 
    if(pollfds.revents & POLLOUT) 
    doWriteAction(i); 
    } 
    } 
    } 


    五、利用rtsig多路复用I/O的Web服务应用模型

    /* 新建并初始化关注信号。*/ 
    sigset_t sigset; 
    siginfo_t siginfo; 
    
    sigemptyset(&sigset); 
    sigaddset(&sigset, SIGRTMIN + 1); 
    sigaddset(&sigset, SIGIO); 
    
    
    /* socket配置和监听。*/ 
    sock = socket(...); 
    bind(sock, ...); 
    listen(sock, ...); 
    
    /* 重新设置描述符可读写时发送的信号值。*/ 
    fcntl(sock, F_SETSIG, SIGRTMIN + 1); 
    
    /* 对socket描述符设置所有者。*/ 
    fcntl(sock, F_SETOWN, getpid()); 
    
    /* 启用描述符的信号驱动I/O模式。*/ 
    fcntl(sock, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR); 
    
    while(1) { 
    struct timespec ts; 
    ts.tv_sec = 1; 
    ts.tv_nsec = 0; 
    
    /*调用sigtimedwait()阻塞等待,等待时间1秒。*/ 
    sigtimedwait(&sigset, &siginfo, &ts); 
    
    /* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/ 
    if(siginfo.si_fd == sock) { 
    new_sock = accept(sock, ...); 
    fcntl(new_sock , F_SETSIG, SIGRTMIN + 1); 
    fcntl(new_sock , F_SETOWN, getpid()); 
    fcntl(new_sock , F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR); 
    }else { 
    /* 对其它描述符发生的事件进行适当处理。*/ 
    doReadAction(i); 
    } 
    }

      

  • 相关阅读:
    (二)柯尼卡美能达bizhub_C368扫描打印机FTP设置内容及打印过程“华文宋体”打印出来乱码解决办法
    (一)柯尼卡美能达bizhub_C368扫描打印机驱动安装及扫描文件配置方法
    (二)谷歌浏览器版本 95.0.4638.54(正式版本) (64 位)表头标签有时候莫名其妙的出现一些不想要的标签解决办法
    (一)Windows7系统共享文件夹失灵,打开“网络发现”后自动关闭有效处理办法
    (三)ADO.NET学习心得
    (二)SQL 常见出现错误(附件、保存表、脱机、自增序列号 )
    (二)C#编程基础复习——变量和常量
    (一)C#编程基础复习——开启编程之旅
    selenium -webdriver
    org.springframework.orm.hibernate3.HibernateSystemException:
  • 原文地址:https://www.cnblogs.com/feika/p/3616658.html
Copyright © 2011-2022 走看看