菜鸟笔记
提升您的技术认知

《unix网络编程》select、shutdown函数-ag真人游戏

《unix网络编程》(11)tcp服务器的几种常见状况分析的“服务器进程终止”提到客户阻塞于fgets所以没办法收到服务器发的fin,只有当客户再次输入文本并发送给服务器后才会从套接字中读取,这时才知道服务器的状态。但这可能已经过了很长时间。这样的进程就需要预先告知内核的能力,使得内核一旦发现进程指定的一个或多个i/o条件就绪(即,输入已经准备好读取,或描述符能够承接更多输出),它就通知进程。这种能力就是i/o复用(i/o mutiplexing)。该能力由select和poll支持

该函数允许进程指示内核等待多个事件中的任何一个发生,并只在有一个或多个事件发生或经历了一段指定的时间后才唤醒它。

select函数及参数

#include 
#include 
int select(int maxfdp1, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);
//返回:若有就绪描述符则返回就绪描述符的数目,若超时返回0,若出错返回-1

参数:

(1) timeout:告知内核等待指定描述符中任何一个就绪花费的最长时间,其timeval结构用于指定秒数和微妙数。

//timeval结构:
struct timeval
{
    long    tv_sec;     /* seconds */
    long    tv_usec;    /* microseconds */
};

使用select,设置其3个set为空指针, nfds为0, 一个非空的timeout来达到较为
精确的sleep(单位为微秒),普通的sleep单位为


timeout取值:

         (1)timeout== null,仅当一个描述符准备好i/o时才返回。

         (2)timeout->tv_sec == 0 && tvptr->tv_usec == 0,立即返回,称为
轮询
五种i/o模型)。

         (3) timeout->tv_sec != 0 || tvptr->tv_usec !=0, 等待特定时间长度,超时返回0;
在这段时间内如果有描述符准备好就返回。

(2)中间的三个参数:指定要让内核测试读、写、异常的描述符,若对某一个不感兴趣可置为null

          这三个参数都是socket,调用函数时,用于指定所关心的描述符的值;函数返回时,结果将指示哪些描述符已经就绪。

         select使用描述符集,通常是一个整数数组,其中每个整数的一位对应一个描述符。而poll是用可变长度的结构数组,每个结构代表一个描述符

 通过fd_set的数据类型和四个宏实现:

       fd_clr(int fd, fd_set *set);  //关闭fd_set中的fd位
       fd_isset(int fd, fd_set *set); //测试该位是否打开,如果为1则该位对应描述符就绪
       fd_set(int fd, fd_set *set);  //打开该fd位
       fd_zero(fd_set *set);         //清空所有位

如下打开描述符1、4位:

fd_set rset;
fd_zero(&rset);  //清空所有,每次调用select都要清空为0
fd_set(1,&rset);  //调用select将我们关心的位置为1.
fd_set(4,&rset);

(3)maxfdp1参数指定待测试的描述符的个数,其值为最大待测试描述符加1。例如上例打开1、4描述符,那么这里maxfdp1值为5。

描述符就绪条件

当某套接字发生错误,将由select标记为既可读又可写。

终止网络连接通常使用close函数。

不过close有两个限制,但可通过shutdown函数避免

(1)close把描述符引用计数减1,仅在该计数为0时才关闭套接字。shutdown可以不管引用计数就激发tcp的正常连接终止。

(2)close终止读和写两个方向的数据传输。有时候需要告诉对端我们已经发完数据,即使对端仍有数据发送

#include 
int shutdown(int sockfd, int howto);
//成功返回0,出错返回-1

shutdown允许我们处理批量数据,典型情况:

该函数行为依赖于howto参数:

(1)shut_rd

           关闭连接读这一半——套接字不再有数据接收,而且套接字接收缓冲区现有数据丢弃。不再对这样的套接字调用读函数。来自对端的数据都被确认并丢弃

(2)shut_wr

          关闭连接写这一半,这称为半关闭。当前留在套接字缓冲区内的数据将被发送掉,后跟tcp的正常连接终止序列。

(3)shut_rdwr

         连接的读和写都关闭。

网站地图