chapter6

  •  6.1 概述
  • I/O复用典型使用在下列网络应用场合。
    •   (1):当客户处理多个描述符时,必须使用IO复用
    •   (2):一个客户同时处理多个套接字是可能的,不过不叫少见。
    •   (3):如果一个TCP服务器既要处理监听套接字,又要处理已连接套接字。
    •   (4):如果一个服务器既要处理TCP,又要处理UDP
    •   (5):如果一个服务器要处理多个服务或多个协议
    •    IO复用并非只限于网络,许多重要的应用程序也需要使用这项技术。
  • 6.2 I/O模型
  • 在Unix下可用的5种I/O模型的基本区别:
    •   (1)阻塞式I/O
    •   (2)非阻塞式I/O
    •   (3)I/O复用(select和poll)
    •   (4)信号驱动式I/O(SIGIO)
    •   (5)异步I/O(POSIX的aio_系列函数)
    • 6.2.1 阻塞式I/O
    • 6.2.2 非阻塞式I/O模型
    • 6.2.3 I/O复用模型
      • 有个I/O复用,我们就可以调用select或poll,阻塞在这两个系统调用中的某一个之上,而不是阻塞在真正的I/O系统调用上。
    • 6.2.4 信号驱动式I/O模型
      • 我们也可以用信号,让内核在描述符就绪时发送SIGIO信号通知我们。我们称这种模型为信号驱动式I/O
    • 6.2.5 异步I/O模型
  •  6.3 select函数
    • 该函数允许进程指示内核等待多个事件中的任何一个发生,并且在有一个或多个事件发生或经历一段指定的时间后才唤醒它。
    • 我们调用select告知内核对那些描述符(就读写或异常)感兴趣以及等待多长时间。
    • #include <sys/select.h>
    • #include <sys/time.h>
    • int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, cosnt struct timeval *timeout);
      • maxfdp1:最大的描述符ID+1
    • struct timeval
    • {
      • long tv_sec; //秒
      • long tv_usec;//微妙
    • };
    • void FD_ZERO(fd_set *fdset);
    • void FD_SET(int fd, fd_set *fdset);
    • void FD_CLR(int fd, fd_set *fdset);
    • int FD_ISSET(int fd, fd_set *fdset);
    • 6.3.1描述符就绪条件
      • (1):满足下列4个条件中的任何一个时,一个套接字准备好读

        • a):
        • ......
    • 6.3.2 select的最大描述符
  • 6.4 str_cli函数
  • 6.5 批量输入
  • 6.6 shutdown函数
    • 终止网络连接的方法不是调用close函数。不过close有两个限制,却可以使用shutdown来避免
    • (1):close把描述符的引用计数减1,但在该计数为0时才关闭套接字
    • (2):close终止读和写两个方向的数据传送。
      • #include <sys/socket.h>
      • int shutdown(int sockfd, int howto);
        • OK : 0 FAILED:-1
  • 6.8 TCP Service
    •  /* include fig01 */
      #include "unp.h" int
      main(int argc, char **argv)
      {
      int i, maxi, maxfd, listenfd, connfd, sockfd;
      int nready, client[FD_SETSIZE];
      ssize_t n;
      fd_set rset, allset;
      char buf[MAXLINE];
      socklen_t clilen;
      struct sockaddr_in cliaddr, servaddr; listenfd = Socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr, sizeof(servaddr));
      servaddr.sin_family = AF_INET;
      servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
      servaddr.sin_port = htons(SERV_PORT); Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); Listen(listenfd, LISTENQ); maxfd = listenfd; /* initialize */
      maxi = -; /* index into client[] array */
      for (i = ; i < FD_SETSIZE; i++)
      client[i] = -; /* -1 indicates available entry */
      FD_ZERO(&allset);
      FD_SET(listenfd, &allset);
      /* end fig01 */ /* include fig02 */
      for ( ; ; ) {
      rset = allset; /* structure assignment */
      nready = Select(maxfd+, &rset, NULL, NULL, NULL); if (FD_ISSET(listenfd, &rset)) { /* new client connection */
      clilen = sizeof(cliaddr);
      connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
      #ifdef NOTDEF
      printf("new client: %s, port %d\n",
      Inet_ntop(AF_INET, &cliaddr.sin_addr, , NULL),
      ntohs(cliaddr.sin_port));
      #endif for (i = ; i < FD_SETSIZE; i++)
      if (client[i] < ) {
      client[i] = connfd; /* save descriptor */
      break;
      }
      if (i == FD_SETSIZE)
      err_quit("too many clients"); FD_SET(connfd, &allset); /* add new descriptor to set */
      if (connfd > maxfd)
      maxfd = connfd; /* for select */
      if (i > maxi)
      maxi = i; /* max index in client[] array */ if (--nready <= )
      continue; /* no more readable descriptors */
      } for (i = ; i <= maxi; i++) { /* check all clients for data */
      if ( (sockfd = client[i]) < )
      continue;
      if (FD_ISSET(sockfd, &rset)) {
      if ( (n = Read(sockfd, buf, MAXLINE)) == ) {
      /*4connection closed by client */
      Close(sockfd);
      FD_CLR(sockfd, &allset);
      client[i] = -;
      } else
      Writen(sockfd, buf, n); if (--nready <= )
      break; /* no more readable descriptors */
      }
      }
      }
      }
      /* end fig02 */
  • 6.9 pselect函数
    • #include <sys/select.h>
    • #include <signal.h>
    • #include <time.h>
    • int pselect(int masfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,const struct timespec *timeout,const sigset_t *sigmask);
    • pselect相对于通常的select有两个变化
      • pselect使用timespec结构,而不使用timeval结构。

        • struct timespec{

          • time_t tv_sec;
          • long tv_nsec; // 纳秒书
        • };
      • pselect函数增加了第六个参数:一个指向信号掩码的指针。
        • ......
  • 6.10 poll函数
    • #include <poll.h>
    • int poll(struct pollfd *fdarray,unsigned long nfds, int timeout);
    • 如果有就绪描述符则返回去数目,若超时则为0,若出错则为-1
    • struct pollfd{
      • int fd;
      • short events;
      • short revents;
      • };

【Unix网络编程】chapter6IO复用的更多相关文章

  1. 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数

    本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...

  2. UNIX网络编程——套接字选项(心跳检测、绑定地址复用)

    /* 设置套接字选项周期性消息检测连通性 心跳包. 心博.主要用于长连接. * 参数:套接字, 1或0开启, 首次间隔时间, 两次间隔时间, 断开次数 */ void setKeepAlive( in ...

  3. UNIX网络编程 第6章 I/O复用:select和poll函数

    UNIX网络编程 第6章 I/O复用:select和poll函数

  4. Linux网络编程-IO复用技术

    IO复用是Linux中的IO模型之一,IO复用就是进程预先告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程进程处理,从而不会在单个IO上阻塞了.Linux中,提 ...

  5. Unix网络编程--卷一:套接字联网API

    UNIX网络编程--卷一:套接字联网API 本书面对的读者是那些希望自己编写的程序能够使用成为套接字(socket)的API进行彼此通信的人. 目录: 0.准备环境 1.简介 2.传输层:TCP.UD ...

  6. [转载] 读《UNIX网络编程 卷1:套接字联网API》

    原文: http://cstdlib.com/tech/2014/10/09/read-unix-network-programming-1/ 文章写的很清楚, 适合初学者 最近看了<UNIX网 ...

  7. UNIX网络编程——客户/服务器心搏函数

    阅读此博客时,可以参考以前的博客<<UNIX网络编程--socket的keep-alive>>和<<UNIX网络编程--套接字选项(心跳检测.绑定地址复用)> ...

  8. Unix网络编程中的五种I/O模型_转

    转自:Unix网络编程中的的五种I/O模型 下面主要是把unp第六章介绍的五种I/O模型. 1. 阻塞I/O模型 例如UDP函数recvfrom的内核到应用层.应用层到内核的调用过程是这样的:首先把描 ...

  9. UNIX网络编程——网络I/O模型

    在学习UNIX网络编程的时候.一開始分不清 同步 和 异步,所以还是总结一下,理清下他们的差别比較好. IO分类 IO依据对IO的调度方式可分为堵塞IO.非堵塞IO.IO复用.信号驱动IO.异步IO. ...

  10. 《Unix 网络编程》08:基本UDP套接字编程

    基本UDP套接字编程 系列文章导航:<Unix 网络编程>笔记 UDP 概述 流程图 recvfrom 和 sendto #include <sys/socket.h> ssi ...

随机推荐

  1. A* 寻路学习

    启发式搜索:启发式搜索就是在状态空间中的搜索.对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标.这样可以省略大量无谓的搜索路径,提高了效率.在启发式搜索中,对位置的估价是十分重 ...

  2. C# Monitor的Wait和Pulse方法使用详解

    [转载]http://blog.csdn.net/qqsttt/article/details/24777553 Monitor的Wait和Pulse方法在线程的同步锁使用中是比较复杂的,理解稍微困难 ...

  3. [转]浅谈UML的概念和模型之UML九种图

    目录: UML的视图 UML的九种图 UML中类间的关系 上文我们介绍了,UML的视图,在每一种视图中都包含一个或多种图.本文我们重点讲解UML每种图的细节问题: 1.用例图(use case dia ...

  4. Chrome 66 禁止声音自动播放

    声音无法自动播放一直在IOS/Android上面都是一个惯例, 桌面端的 Safari在2017年的11版本中也宣布禁止带有声音的多媒体自动播放, 紧接着2018年4月份Chrome发布的66版本也正 ...

  5. CommonJS 规范中的 module、module.exports 区别

    CommonJS 规范中的 module.module.exports 区别 CommonJS规范规定,每个模块内部,module变量代表当前模块.这个变量是一个对象,它的exports属性(即mod ...

  6. vue-cli 2.x 项目优化之:引入本地静态库文件

    demo地址:https://github.com/cag2050/vue_cli_optimize_static_resource vue-cli 将静态资源文件放到 static 文件夹下并引用: ...

  7. django 保存中文到mysql 报错django.db.utils.DatabaseError: Incorrect string value: '\xE5\xBE\x88\xE7\x81\xB5

    分析: 1.尝试在Python中对数据转码成utf8,'中文'.encode("utf-8"),还是报错 2.观察堆栈发现应该是操作mysql数据库的时候,将数据插入表里出错 所以 ...

  8. Jmeter之函数助手

    本文转载自:心的开始  Emily0120 JMeter函数是一些能够转化在测试树中取样器或者其他配置元件的域的特殊值.一个函数的调用就像这样:${_functionName(var1,var2,va ...

  9. [转载] C# DllImport用法和路径问题

    DllImport是System.Runtime.InteropServices命名空间下的一个属性类,其功能是提供从非托管DLL导出的函数的必要调用信息. DllImport属性应用于方法,要求最少 ...

  10. mysql 删除数据库中所有的表中的数据,只删database下面所有的表。

    select concat('drop table ',table_name,';') from TABLES where table_schema='数据库名称'; select concat('t ...