28、select函数

在之前的文章中,我们介绍了TCP Socket函数的使用,并实现了简单的TCP Server和TCP Client,采用的是TCP阻塞模式。关于阻塞模式的介绍,可以参考https://blog.csdn.net/w00347190/article/details/100172662。采用阻塞模式时,线程会处于等待状态,一个线程只能处理一个连接,服务端想要处理多个客户端连接,必须为每个连接创建一个线程,线程/进程的创建以及切换,又会带来新的开销,这些开销是非常昂贵的,因为cpu同时运行的线程只有屈指可数的几个。

为了解决上述问题,在实际项目中,一般都是采用非阻塞模式,采用阻塞模式会带来新的问题:函数调用会立即返回,无法通过返回值获取操作结果。为了解决这种问题,需要在循环中多次调用函数,直到相关操作完成,函数返回预期值,这样多次循环调用会消耗CPU时间,影响性能(线程阻塞时,无法处理其他业务,但是不会影响CPU开销)。在实际项目中,一般都是使用select函数和非阻塞模式相结合的方式。

select函数:

头文件:
#include <sys/select.h>
#include <sys/time.h>

原型:
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);

参数:
maxfdp1:select监视的文件描述符数,视进程中打开的文件数而定,设为你要监视各文件中的最大文件号加1;
readset:select监视的可读文件描述符集合;
writeset:select监视的可写文件描述符集合;
exceptset:select监视的异常文件描述符集合;
timeout:本次select()的超时结束时间;

返回值:
若有就绪描述符,则返回就绪描述符数目;若超时则返回0,出错返回-1。

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

即:调用select()函数后,它会指示内核监视readset、writeset、exceptset集合中的所有文件描述符对应的I/O,同时select函数会等待阻塞,直到readset中某个I/O可读、writeset中某个I/O可写、exceptset中某个I/O异常时(我们称为I/O就绪),select函数返回,并将readset、writeset、exceptset中非就绪的文件描述符对应的bit位清零

通过select函数实现Socket通信的常规步骤为:

(1)将需要监视的Socket的文件描述符添加到readset、writeset、exceptset集合,需要先对这3个fd_set进行FD_ZERO操作;

(2)调用select函数,等待I/O事件;

(3)select函数返回后,通过FD_ISSET获取I/O就绪的文件描述符,进行读写操作;

(4)重新将需要监视的Socket的文件描述符添加到readset、writeset、exceptset集合;

上述对fd_set的操作,需要掌握相关的宏定义,请参考《27、fd_set与FD_SETSIZE详解》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值