一 设计模式
reactor
二 多路复用
1 select
原型:
int select(int nfds ,//
fd_set* readfds ,// 读事件描述符集合
fd_set* writefds ,// 写事件描述符集合
fd_set* exceptfds,// 异常事件描述集合
const struct timeval* timeout);// select等待的时间
支持:
Linux,Windows
2 epoll
函数原型:
int epoll_create(int size);// 创建size个事件描述符集合
// 给描述符设置所关注的事件,并把它添加到内核的事件列表中
int epoll_ctl(int epfd,
int op,// EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD三种对事件的操作
int fd,
struct epoll_event *event);
// 消息循环
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)
支持:
Linux
3 poll
原型:
int poll(struct pollfd *fdarray, unsigned long nfds, int timeout);
支持:
Linux
4 dev/poll
函数原型:
int dpfd = open("/dev/poll", O_RDWR);// 获得文件描述符
size_t pwrite(int fd, (struct pollfd *)events, size_t count, off_t offset);// 增加事件
ioctl(int fd, int command, (char *) argstruct);// 事件循环
支持:
Solaris
5 kqueue
函数原型:
// 注册和反注册事件
int kevent(int kq, const struct kevent *changelist, int nchanges,
struct kevent *eventlist, int nevents,
const struct timespec *timeout);
int kqueue(void); // 创建监听
支持:
FreeBSD
三 消息处理模式
当服务器每收到一个请求时,通常有以下几种处理模型:
(1)创建一个新的进程,来处理该请求;实现简单,但创建进程多开销大,消耗服务器性能,进程切换开销大。
(2)创建一个新的线程,来处理该请求;涉及到线程同步,需要解决加锁和死锁问题,而且线程切换有开销。
(3)放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求。失去了并发性,不能充分利用多核cpu。