zoukankan      html  css  js  c++  java
  • I/O多路复用方案

    1. 本节思维导图

      

    2. 基本的网络编程接口

    2.1 基于TCP的通信模型

      

    2.2 基于UDP的通信模型

    3. 非阻塞的服务器程序

      file、pipe、fifo、socket在默认创建过程中都是阻塞的(block),非阻塞的接口相比于阻塞型接口的显著差异在于,在被调用之后立即返回,在linux中我们可以使用fcntl()函数来设置描述符的状态

      fcntl(fd,F_SETFL, O_NOBLOCK)

      fcntl函数重点关注第二个参数中的F_SETFL和F_GETFL设置或获取描述符的状态

      状态包括:O_NONBLOCK O_APPEND O_ASYNC

      O_DIRCT(最小化或去掉reading和writing的缓存影响.系统将企图避免缓存你的读或写的数据)

      在非阻塞的状态下,recv()接口在被调用后立即返回,返回值代表了不同的含义:

    1)recv()返回值大于0,表示接收数据完毕,返回值即是接收到的字节数
    (2)recv()返回值为0,表示链接已经正常断开
    (3)recv()返回值为-1,且errno等于EAGAIN,表示recv操作还没有执行完成
    (4)recv()返回值为-1,且error不等于EAGAIN,表示recv操作遇到系统错误errno

      注意:绝不推荐循环调用recv()来检测“操作是否完成”,循环调用recv将大幅度推高CPU占用率,实际操作系统提供了更为高效的方法来检测“操作是否完成”,比如select、epoll

    4. select()接口的基于事件驱动的服务器模型

      大部分UNIX/LINUX都支持select函数,改函数用于探测多个文件句柄的状态变化,以下为select接口的原型:

    FD_ZERO(int fd, fd_set *fds) // fd_set类型变量的所有位都设为0
    FD_SET(int fd, fd_set *fds ) // 设置变量的某个位置位
    FD_ISSET(int fd, fd_set *fds) // 测试某个位置是否被置位
    FD_CLR(int fd, fd_set *fds)   // 清除某个位时可以使用
    int select(int nfds, fd_set *readfds, fd_set *writefds, df_set *exceptfds, struct timeval *timeout)

      关于select更加详细的说明和使用请参考:https://www.cnblogs.com/skyfsm/p/7079458.html

    5. 使用epoll实现异步事件通知模型

      已经在前面的博客中总结了epoll用法,具体参考:linux之epoll

      这里重点说明下accept的使用技巧:

      (1)阻塞模式accept存在的问题,考虑这种情况:TCP链接被客户端夭折,即在服务器调用accept之前,客户端主动发送RST终止链接,导致刚刚建立的链接从就绪队列中移除,如果套接口被设置为阻塞模式,服务器就会一直阻塞在accept调用上,直到其它某个客户端建立一个新的链接为止,但是在此期间,服务器单纯地阻塞在accept调用上,就需队列中的其它描述符都得不到处理

      解决方法:把监听套接口设为非阻塞,当客户端在服务器调用accept之前中止某个连接时,accept调用可以立即返回-1,这时源自Berkeley的实现会在内核中处理该事件,并不会将该事件同质epoll。而其它实现把errno设置为ECONNABORTED或者EPROTo错误,我们可以忽略这两个错误。

      (2)ET模式相爱的accept存在的问题,考虑这种情况:多个链接同时到达时,服务器的TCP就绪队列瞬间基类多喝就绪链接,由于是边缘触发模式,epoll只会通知一次,accept只处理第一个链接,导致TCP就绪队列中剩下的链接都得不到处理

      解决方法:用while循环包住accept,处理完TCP就绪队列中的所有链接后再退出循环,如何知道是否处理完就绪队列中的所有链接呢?accept返回-1并且errno设置为EAGAIN就表示所有的链接都处理完。

  • 相关阅读:
    Marker
    Log4j 2
    Spring 中 CharacterEncodingFilter 失效?
    Java 泛型通配符
    待修 Bug
    Java Class SecurityManager
    bzoj 5210: 最大连通子块和【动态dp+树剖+线段树+堆】
    洛谷 P4719 【模板】动态dp【动态dp】
    bzoj 2555: SubString【后缀自动机+LCT】
    洛谷 P4125 [WC2012]记忆中的水杉树【扫描线+set+线段树】
  • 原文地址:https://www.cnblogs.com/xiaobingqianrui/p/9329226.html
Copyright © 2011-2022 走看看