美文网首页程序员linux c/c++杂谈我用 Linux
linux网络编程系列(十一)--select基本使用以及它和e

linux网络编程系列(十一)--select基本使用以及它和e

作者: cpp加油站 | 来源:发表于2019-06-28 13:12 被阅读11次

1. select函数

复用IO还有一种就是select模型,我们下面就来简单介绍一下select用法。

1.1 select函数原型

int select(int maxfdp, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
//fd_set是一个集合,里面存放的是文件描述符,如下是一些可以操作fd_set的宏:
fd_set set;
FD_ZERO(&set); //清空set
FD_SET(fd, &set); //将fd加入set
FD_CLR(fd, &set); //将fd从set中清除
FD_ISSET(fd, &set); //如果fd在set中则为真,通常用来检查某个文件描述符是否在描述符集合中,然后去读、写、接收连接

struct timeval则代表超时时间,有两个成员,一个是秒数,一个是毫秒;
select参数说明:

  • maxfdp 代表集合中文件描述符的范围, 即所有文件描述符的最大值加1;
  • readfds 指针指向文件描述符集合,如果描述符中有一个文件可读, select就返回一个大于0的值(准备就绪的描述符数量), 表示有文件可读。没有文件可读时则判断是否超时, 若超时,返回0, 否则发生错误返回负值, 当传入NULL时, 则表示不关心是否有文件可读;
  • writefds 指针指向文件描述符集合,如果描述符中有一个文件可写, select就返回一个大于0的值, 表示有文件可写。没有文件可写时则判断是否超时, 若超时,返回0, 否则发生错误返回负值, 当传入NULL时, 则表示不关心是否有文件可写;
  • errorfds 同上面两个参数,用来监视文件错误异常;
  • timeout 传入NULL时,没有超时时间,会将select置于阻塞状态,一直等到监视的文件描述符集合中有文件描述符发生变化为知;
    若将超时时间设为0,则select会处于非阻塞状态,不管文件描述符是否有变化,立即返回,文件描述符有变化时,返回大于0, 无变化时, 返回0;
    超时时间大于0,则如果有文件描述符发生变化才返回,否则直到超时,才返回;

1.2 select函数调用

socket()/bind()/listen()/select()/send()/recv()/close()

1.3 select使用

使用select也需先将socket设置为非阻塞的
下面演示如何使用select函数:

    struct timeval TimeOut, *pTimeOut = NULL;
    fd_set readfds, writefds;
 FD_ZERO (&readfds);
    FD_SET (m_nSock, &readfds);
    writefds = readfds;
    TimeOut.tv_sec = 5;
    TimeOut.tv_usec=0;
 pTimeOut = &TimeOut;
 while(1)
 {
  if ((nRetVal = select (m_nSock + 1,&readfds, &writefds, NULL, pTimeOut)) == 0)
  {
   //超时
   return 0;
  }
  else if ((nRetVal < 0) && (errno == EINTR || errno == EPIPE))
   continue;
 }

2. 使用select如何检测连接已经关闭

如果连接断开了,select会返回1,但单纯的select返回1并不能说明连接断开了,也可能是有数据可读,所以此时需要再判断一下read或者recv的返回值,如果返回0,就说明连接断开了。
伪代码如下:

fd_set read_set;
struct timeval t_o;
FD_ZERO(&read_set);
FD_SET(lSockFd,&read_set);
t_o.tv_sec = n;/* 超时秒数*/
ret = select(lSockFd + 1,&read_set,NULL,NULL,&t_o);
if(ret == 1)
{ 
 count = recv(lSockFd,buf,LEN,0);
 if((count == 0))
 {
  //说明连接断开
 }
}

3. select和epoll的区别

  • select是轮询fd,而epoll是先将文件描述符注册到内核,一旦文件描述符发生变化,内核会采用回调机制激活这个文件描述符,这样epoll_wait就会知道;
  • epoll监视的文件描述符数量没有限制,当然跟内存也有关,而select则在内核头文件中定义最多监视1024个文件描述符;
  • epoll效率不会随着文件描述符数量的增长而直线下降;
  • epoll使用mmap加速内核和用户空间的信息传递,避免多余的内存拷贝;

本人在简书上写的内容均为本人原创,转载需经本人同意。简书主页:https://www.jianshu.com/u/e8c7bb5e3257

相关文章

  • linux网络编程系列(十一)--select基本使用以及它和e

    1. select函数 复用IO还有一种就是select模型,我们下面就来简单介绍一下select用法。 1.1 ...

  • Linux多线程服务端编程一

    这个系列主要是阅读书籍《Linux多线程编程 使用muduo网络库》的一些心得和思考,以及一些延伸,以及记录些技术...

  • Linux网络编程篇之ICMP协议分析及ping程序实现

    Linux网络编程系列: Linux网络编程篇之Socket编程预备知识 Linux网络编程篇之TCP协议分析及聊...

  • epoll使用详解

    在Linux网络编程当中,很长时间都是使用select来做事件的触发,而在新的linux内核当中,有一种替换他的机...

  • 从linux源码看epoll

    前言 在linux的高性能网络编程中,绕不开的就是epoll。和select、poll等系统调用相比,epoll在...

  • 从linux源码看epoll

    前言 在linux的高性能网络编程中,绕不开的就是epoll。和select、poll等系统调用相比,epoll在...

  • Socket编程发展

    Linux Socket 编程领域,为了处理大量连接请求场景,需要使用非阻塞 I/O 和复用。select、pol...

  • Linux中select、poll和epoll的区别

    在Linux Socket服务器短编程时,为了处理大量客户的连接请求,需要使用非阻塞I/O和复用,select、p...

  • 网络编程-select

    什么是UDP UDP,是User Datagram Protocol的简称, 中文名是用户数据包协议,是 OSI ...

  • TW训练营总结

    工具的使用github的基本使用markdown的使用每日站会linux命令行 编程语言及其思想shell编程部分...

网友评论

    本文标题:linux网络编程系列(十一)--select基本使用以及它和e

    本文链接:https://www.haomeiwen.com/subject/iauscctx.html