阻塞模式下服务端要解决多个客户连接的问题的3个思路:linux
思路1,若是连接不少(C10k)线程就会不少,消耗系统资源,并增长调度成本(Java BIO)。数组
思路2,每次都要遍历一边全部socket,连接不少时效率低,可能大部分连接都没数据(select)。socket
思路3,比较理想(epoll)。函数
函数原型:性能
select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, struct timeval *restrict timeout);
select() 检查 readfds
, writefds
中的 io描符是否可读、可写了,若是有ready状态的,函数就返回。 nfds
是总共fd的个数,而不是最大的fd。线程
使用select函数步骤:指针
fd_set 是什么?
一个结构体:rest
typedef struct fd_set { __int32_t fds_bits[__DARWIN_howmany(__DARWIN_FD_SETSIZE, __DARWIN_NFDBITS)]; } fd_set;
结构体中有一个数组,默认是是1024,这就是linux中select的函数限制最大连接数的缘由。
从新编译内核才能提升这个数字。 FD_ISSET
就是取对应位置状态值(0,1),而且在用户空间,
用户须要遍历编一遍这个数组来检查是哪一个socket有数据。code
select的内部实现:队列
select的问题:
每次调用select都会有以上两次传递和两次遍历,当连接个数多时,性能降低比较快:
select可能的改进: