socket通信之最简单的I/O 多路复用

本文介绍了Linux下的I/O多路复用技术,并详细解释了select()函数的使用方法,包括参数说明、宏定义、结构体定义以及一个完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Linux/UNIX 下,有下面这五种I/O 操作方式:
1.阻塞 I/O
2. 非阻塞 I/O
3.I/O 多路复用
4.信号驱动 I/O(SIGIO)
5.异步 I/O

至于每种模式的含义自己去查吧,百度百科、wiki百科介绍的都很详细,要是介绍的话,我也就是抄袭过来,要学会使用搜索引擎~~

还记得上一篇文章的例子吧,那就是基于阻塞I/O模式的,简单的不能再简单的socket通信,写那篇主要是为了对socket通信有个简单的认识及明白各个函数的使用方法,以下是为更深一步做基础。

这篇要介绍下I/O多路复用,重要的函数:

1.select()

#include <sys/time.h>

#include <unistd.h>

int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout);

参数maxfd是需要监视的最大的文件描述符值+1;

rdset,wrset,exset分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集 合及异常文件描述符的集合。

struct timeval结构用于描述一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为0。

注意:关于返回值问题,若有就绪描述符则为其数目,若超时则为0,若出错则为1

2.几个重要的宏

FD_CLR(inr fd,fd_set* set);用来清除描述词组 set中相关 fd的位 
FD_ISSET(int fd,fd_set *set);用来测试描述词组 set中相关 fd的位是否为真 
FD_SET(int fd,fd_set*set);用来设置描述词组 set中相关 fd的位 
FD_ZERO(fd_set *set);用来清除描述词组 set的全部位参数

3.一个重要的结构体
timeout为结构 timeval,用来设置 select()的等待时间,其结构定义如下:
struct timeval

 time_t tv_sec; 
 time_t tv_usec;
};
下面是常见的程序片段
  fs_set readset;
  FD_ZERO(&readset);
  FD_SET(fd,&readset);
  select(fd+1,&readset,NULL,NULL,NULL);
  if(FD_ISSET(fd,readset){……}

完成的代码例子:

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <sys/time.h>     
  3. #include <sys/types.h>    
  4. #include <unistd.h>       
  5. #define TIMEOUT 5 /* select timeout in seconds *  
  6. #define BUF_LEN 1024 /* read buffer in bytes */   
  7. int main (void)     
  8. {   
  9.     struct timeval tv;  
  10.     fd_set readfds;     
  11.     int ret;    
  12.     /* Wait on stdin for input. */    
  13.     FD_ZERO(&readfds);  
  14.     FD_SET(STDIN_FILENO, &readfds);   
  15.     /* Wait up to five seconds. */    
  16.     tv.tv_sec = TIMEOUT;      
  17.     tv.tv_usec = 0;     
  18.     /* All right, now block! */       
  19.     ret = select (STDIN_FILENO + 1,&readfds,NULL,NULL,&tv);  
  20.     if (ret == -1)   
  21.     {    
  22.         perror("select");   
  23.         return 1;   
  24.     }   
  25.     else if (!ret)   
  26.     {    
  27.         printf ("%d seconds elapsed.\n", TIMEOUT);        
  28.         return 0;   
  29.     }   
  30.     /* 
  31.     * Is our file descriptor ready to read?  
  32.     * (It must be, as it was the only fd that        
  33.     * we provided and the call returned      
  34.     * nonzero, but we will humor ourselves.) 
  35.     */  
  36.     if (FD_ISSET(STDIN_FILENO, &readfds))   
  37.     {   
  38.         char buf[BUF_LEN+1];  
  39.         int len;  
  40.         /* guaranteed to not block */     
  41.         len = read (STDIN_FILENO, buf, BUF_LEN);  
  42.         if (len == -1)   
  43.         {    
  44.             perror ("read");    
  45.             return 1;   
  46.         }   
  47.         if (len)   
  48.         {  
  49.             buf[len]='\0';      
  50.             printf ("read: %s\n", buf);       
  51.         }   
  52.         return 0;   
  53.     }   
  54.     fprintf (stderr, "This should not happen!\n");    
  55.     return 1;   
  56. }   

代码不是很长,是一个最简单的例子,很好理解。



FROM; http://blog.youkuaiyun.com/xluren/article/details/8045028


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值