《TCP/IP网络编程》第12章 I/O复用

 本章所有示例代码>>github

12.1 基于I/O复用的服务器端

1.       多进程服务器端的缺点

    为了构建并发服务器,只要有客户端连接请求就会创建新进程。这的确是实际操作系统中采用的一种方案,但并非十全十美,因为创建进程时需要大量的运算和内存空间,由于每个进程都具有独立的内存空间,所以相互间的数据交换也要求采用相对复杂的方法(IPC属于相对复杂的方法)。

2.       理解复用

    “在1个通信频道中传递多个数据(信号)的技术。”

    时(time)分复用技术;

    频(frequency)分复用技术;

3.       复用技术在服务器端的应用

    多进程服务器端:

《TCP/IP网络编程》第12章 I/O复用_第1张图片

    采用复用技术的服务器端,无论连接多少客户端,提供服务的进程只有1个:

《TCP/IP网络编程》第12章 I/O复用_第2张图片

12.2 理解select函数并实现服务器端

    运用select函数是最具代表性的实现复用服务器端方法。

1.       select函数的功能和调用顺序

    使用select函数时可以将多个文件描述符集中到一起统一监视,监视项称为“事件”(event):

  • 是否存在套接字接收数据?
  • 无需阻塞传输数据的套接字有哪些?
  • 哪些套接字发生了异常?

    select函数的调用方法和顺序:

《TCP/IP网络编程》第12章 I/O复用_第3张图片

2.       设置文件描述符

    利用select函数可以同时监视多个文件描述符,监视文件描述符可以视为监视套接字。此时首先需要将要监视的文件描述符集中到一起。集中时要按照监视项(接收、传输、异常)进行区分,即按照上述3种监视项分成3类。

    使用fd_set结构体变量执行此操作。该数组是存有0和1的位数组。

    最左端的位表示文件描述符0(所在位置)。如果该位设置为1,则表示该文件描述符是监视对象。

    在fd_set变量中注册或更改值的操作都由下列宏完成:

  • FD_ZERO(fd_set *fdset)将fd_set变量的所有位初始化为0;
  • FD_SET(int fd, fd_set *fdset)在参数fdset指向的变量中注册文件描述符fd的信息;
  • FD_CLR(int fd, fd_set *fdset)从参数fdset指向的变量中清除文件描述符fd的信息;
  • FD_ISSET(int fd, fd_set *fdset)若参数fdset指向的变量中包含文件描述符fd的信息,则返回“真”;

《TCP/IP网络编程》第12章 I/O复用_第4张图片

3.       设置检查(监视)范围及超时

#include
#include
int select(int maxfd,fd_set *readset, fd_set *writeset, fd_set
           *exceptset, conststruct timeval *timeout);
//成功时返回大于0的值,失败时返回-1

    -maxfd:被监听文件描述符个数,通常设置为监听的所有描述符最大值加1因为文件描述符是从0开始的;

    -readset:将所有关注“是否存在待读取数据”的文件描述符注册到fd_set型变量,并传递其地址值;

    -writeset:将所有关注“是否可传输无阻塞数据”的文件描述符注册到fd_set型变量,并传递其地址值;

    -exceptset:将所有关注“是否发生异常”的文件描述符注册到fd_set型变量,并传递其地址值;

    -timeout:调用select函数后,为防止陷入无限阻塞的状态,传递超时(time-out)信息;

    返回值:发生错误时返回-1,超时返回时返回0。因发生关注的事件返回时,返回大于0的值,该值是发生事件的文件描述符;

    第一,文件描述符的监视范围与select函数的第一个参数有关,每次新建文件描述符时,其值都会增1;

    第二,select函数的超时时间与select函数的最后一个参数有关,其中,timeval结构体定义如下:

struct timeval
{
    long tv_sec; // seconds
    long tv_usec; // microsecond
};

    本来select函数只有在监视的文件描述符发生变化时才返回。如果未发生变化,就会进入阻塞状态。指定超时时间就是为了防止这种情况的发生。

4.       调用select函数后查看结果

《TCP/IP网络编程》第12章 I/O复用_第5张图片

    select函数调用完成后,向其传递的fd_set变量中将发生变化。原来为1的所有位均变为0,但发生变化的文件描述符对应位除外。

    调用select函数后,结构体timeval的成员tv_sec和tv_usec的值将被替换为超时前剩余时间。

   






你可能感兴趣的:(网络编程)