1.TCP并发服务器问题
- 服务端需要连接多个客户端时,服务器需要使用accept等待三次握手连接,同时还需要recv等
待接受所有客户端发送的数据,由于accept和recv都是阻塞IO,所以导致程序逻辑无法编写 - 解决方法:
- TCP并发服务器线程/进程模型:
- 优点:实现简单
- 缺点:资源消耗大,每个TCP连接都会分配一个线程任务
- TCP并发服务器多路复用模型
- TCP并发服务器线程/进程模型:
2.Linux系统的4种I/O模型
- 阻塞I/O
- 效率高,数据没来时,CPU阻塞等待,不占用CPU资源
- 非阻塞I/O
- 效率低,需要轮询是否有IO事件发生
- 异步I/O
- 当内核监测到有IO事件发生时,主动向应用层上报信号事件
- 多路复用I/O
- 用一个函数接口监听多个文件描述符是否产生IO事件,只要其中一个产生事件,则不再
阻塞,用户可以处理对应的事件 - select(4个缺点)
- select监听的文件描述符集合是一个数组,是有上限的(一般为1024)
- select监听的文件描述符集合在应用层,当事件发生需要产生一次内核层向应
用层数据的拷贝,会产生资源开销 - select只能工作在水平触发模式(低速模式)
- select必须将所有在文件描述符集合中的元素找一遍才能找到产生事件的文件
描述符
- poll(3个缺点)
- poll监听的事件集合在链表中,没有上限的限制
- 其余与select特点相同(3个缺点)
- epoll
- 没有文件描述符上限的限制
- epoll创建一张内核监听的事件表,所以事件表在内核中,无需与应用层交互效
率高 - epoll可以工作在水平触发(默认)和边沿触发模式(EPOLLET)
- epoll可以将产生事件的所有文件描述符返回,而不需要手动检测所有文件符是
否有事件发生
- 用一个函数接口监听多个文件描述符是否产生IO事件,只要其中一个产生事件,则不再
3.函数接口
1.fcntl
int fcntl(int fd, int cmd, ... /* arg */ );
功能:向文件描述符发送cmd命令
参数:
fd:文件描述符
cmd:
F_GETFL 获得属性
F_SETFL 设置属性
返回值:
成功返回0
失败返回-1
2.select
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
功能:监听文件描述符集合中是否有事件发生
参数:
nfds:最大的文件描述符+1
readfds:读文件描述符集合
writefds:写文件描述符集合
execptfds:其余文件描述符集合
timeout:超时时间,传NULL表示一直阻塞
返回值:
成功返回产生事件的文件描述符个数
失败返回-1
如果超时仍然没有事件发生返回0
void FD_CLR(int fd, fd_set *set);
功能:将文件描述符fd从文件描述符集合中删除
int FD_ISSET(int fd, fd_set *set);
功能:判断fd是否仍在文件描述符集合中
void FD_SET(int fd, fd_set *set);
功能:将fd加入文件描述符集合中
void FD_ZERO(fd_set *set);
功能:将文件描述符集合清零
3.poll
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
功能:监听事件集合中的事件是否发生
参数:
fds:监听事件集合的数组首地址
nfds:事件数组的元素个数
timeout:超时时间, -1 一直阻塞直到事件发生
返回值:
失败返回-1
成功返回产生事件的个数
时间达到没有事件发生返回0
4.epoll
int epoll_create(int size);
功能:创建一张内核监听的事件表
参数:
size:事件表的事件的个数
返回值:
成功返回文件描述符
失败返回-1
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
功能:向内核事件表中添加、修改、删除事件
参数:
epfd:内核事件表的文件描述符
op:EPOLL_CTL_ADD 添加事件
EPOLL_CTL_MOD 修改事件
EPOLL_CTL_DEL 删除事件
fd:操作的文件描述符
event:事件集合
返回值:
成功返回0
失败返回-1
int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
功能:监听事件表中的事件
参数:
epfd:文件描述符
events:存放产生事件的空间的首地址
maxevents:数组的大小
timeout:超时时间
返回值:
成功返回产生事件的文件描述符个数
失败返回-1
时间达到没有事件产生返回0