您的位置:首页 > 其它

【转载】各I/O模型写了对应Web服务应用模型

2013-05-08 17:10 267 查看


【原创】各I/O模型写了对应Web服务应用模型

http://hi.baidu.com/lenky0401/item/ad1f0a0ac3600ce0fe240d6a

//by lenky

利用select多路复用I/O的Web服务应用模型

/* 可读、可写、异常三种文件描述符集的申明和初始化。*/

fd_set readfds, writefds, exceptionfds;

FD_ZERO(&readfds);

FD_ZERO(&writefds);

FD_ZERO(&exceptionfds);

int max_fd;

/* socket配置和监听。*/

sock = socket(...);

bind(sock, ...);

listen(sock, ...);

/* 对socket描述符上发生关心的事件进行注册。*/

FD_SET(&readfds, sock);

max_fd = sock;

while(1) {

int i;

fd_set r,w,e;



/* 为了重复使用readfds 、writefds、exceptionfds,将它们拷贝到临时变量内。*/

memcpy(&r, &readfds, sizeof(fd_set));

memcpy(&w, &writefds, sizeof(fd_set));

memcpy(&e, &exceptionfds, sizeof(fd_set));



/* 利用临时变量调用select()阻塞等待,等待时间为永远等待直到发生事件。*/

select(max_fd + 1, &r, &w, &e, NULL);

/* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/

if(FD_ISSET(&r, sock)){

new_sock = accept(sock, ...);

FD_SET(&readfds, new_sock);

FD_SET(&writefds, new_sock);

max_fd = MAX(max_fd, new_sock);

}

/* 对其它描述符发生的事件进行适当处理。描述符依次递增,最大值各系统有所不同(比如在作者系统上最大为1024),在linux可以用命令ulimit -a查看(用ulimit命令也对该值进行修改)。在freebsd下,用sysctl -a | grep kern.maxfilesperproc来查询和修改。*/

for(i= sock+1; i<max_fd+1; ++i) {

if(FD_ISSET(&r, i))

doReadAction(i);

if(FD_ISSET(&w, i))

doWriteAction(i);

}

}

利用poll多路复用I/O的Web服务应用模型

/* 新建并初始化文件描述符集。*/

struct pollfd fds[MAX_NUM_FDS];

int max_fd;

/* socket配置和监听。*/

sock = socket(...);

bind(sock, ...);

listen(sock, ...);

/* 对socket描述符上发生关心的事件进行注册。*/

fds[0].fd = sock;

fds[0].events = POLLIN;

max_fd = 1;

while(1) {

int i;



/*调用poll()阻塞等待,等待时间为永远等待直到发生事件。*/

poll(fds, max_fd, -1);

/* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/

if(fds[0].revents & POLLIN){

new_sock = accept(sock, ...);

fds[max_fd].fd = new_sock;

fds[max_fd].events = POLLIN | POLLOUT;

++ max_fd;

}

/* 对其它描述符发生的事件进行适当处理。*/

for(i=1; i<max_fd+1; ++i) {

if(fds.revents & POLLIN)

doReadAction(i);

if(fds.revents & POLLOUT)

doWriteAction(i);

}

}

利用epoll多路复用I/O的Web服务应用模型

/* 新建并初始化文件描述符集。*/

struct epoll_event ev;

struct epoll_event events[MAX_EVENTS];

/* 创建epoll句柄。*/

int epfd = epoll_create(MAX_EVENTS);

/* socket配置和监听。*/

sock = socket(...);

bind(sock, ...);

listen(sock, ...);

/* 对socket描述符上发生关心的事件进行注册。*/

ev.events = EPOLLIN;

ev.data.fd = sock;

epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev);

while(1) {

int i;

/*调用epoll_wait()阻塞等待,等待时间为永远等待直到发生事件。*/

int n = epoll_wait(epfd, events, MAX_EVENTS, -1);

for(i=0; i<n; ++i) {

/* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/

if(events.data.fd == sock) {

if(events.events & POLLIN){

new_sock = accept(sock, ...);

ev.events = EPOLLIN | POLLOUT;

ev.data.fd = new_sock;

epoll_ctl(epfd, EPOLL_CTL_ADD, new_sock, &ev);

}

}else{

/* 对其它描述符发生的事件进行适当处理。*/

if(events.events & POLLIN)

doReadAction(i);

if(events.events & POLLOUT)

doWriteAction(i);

}

}

}

利用kqueue多路复用I/O的Web服务应用模型

/* 新建并初始化文件描述符集。*/

struct kevent changelist[MAX_EVENTS];

struct kevent eventlist[MAX_EVENTS];

int count = 0;

/* 创建kqueue句柄。*/

int kqfd = kqueue();

/* socket配置和监听。*/

sock = socket(...);

bind(sock, ...);

listen(sock, ...);

/* 对socket描述符上发生关心的事件进行注册。*/

EV_SET(&changelist[0], sock, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR,

0, 0, 0);

++ count;

while(1) {

int i;

/*调用kevent()阻塞等待,等待时间为永远等待直到发生事件。*/

int n = kevent(kqfd, changelist, count, eventlist, count, NULL);

for(i=0; i<n; ++i) {

/* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/

if(eventlist.ident == sock) {

new_sock = accept(sock, ...);

EV_SET(&changelist[count], new_sock, EVFILT_READ,

EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);

++ count;

}else{

/* 对其它描述符发生的事件进行适当处理。*/

doReadAction(i);

}

}

}

利用/dev/poll多路复用I/O的Web服务应用模型

/* 新建并初始化文件描述符集。*/

struct pollfd pfd;

struct pollfd pollfds[MAX_EVENTS];

struct dvpoll dopoll;

int count = 0;

/* 打开/dev/poll设备,创建poll句柄。*/

int dpfd = open("/dev/poll", O_RDWR);

/* socket配置和监听。*/

sock = socket(...);

bind(sock, ...);

listen(sock, ...);

/* 对socket描述符上发生关心的事件进行注册。*/

pfd.fd = sock;

pfd.events = EPOLLIN;

pfd.revents = 0;

write(dpfd, pfd, sizeof(pfd));

++ count;

while(1) {

int i;

/*调用ioctl()阻塞等待,等待时间为永远等待直到发生事件。*/

dopoll.dp_timeout = -1;

dopoll.dp_nfds = count;

dopoll.dp_fds = &pollfds;

int n = ioctl(dpfd, DP_POLL, &dopoll);

for(i=0; i<n; ++i) {

/* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/

if(pollfds.fd == sock) {

if(pollfds.revents & POLLIN){

new_sock = accept(sock, ...);

pfd.fd = new_sock;

pfd.events = EPOLLIN | POLLOUT;

pfd.revents = 0;

write(dpfd, pfd, sizeof(pfd));

++ count;

}

}else{

/* 对其它描述符发生的事件进行适当处理。*/

if(pollfds.revents & POLLIN)

doReadAction(i);

if(pollfds.revents & POLLOUT)

doWriteAction(i);

}

}

}

利用rtsig多路复用I/O的Web服务应用模型

/* 新建并初始化关注信号。*/

sigset_t sigset;

siginfo_t siginfo;

sigemptyset(&sigset);

sigaddset(&sigset, SIGRTMIN + 1);

sigaddset(&sigset, SIGIO);

/* socket配置和监听。*/

sock = socket(...);

bind(sock, ...);

listen(sock, ...);

/* 重新设置描述符可读写时发送的信号值。*/

fcntl(sock, F_SETSIG, SIGRTMIN + 1);

/* 对socket描述符设置所有者。*/

fcntl(sock, F_SETOWN, getpid());

/* 启用描述符的信号驱动I/O模式。*/

fcntl(sock, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);

while(1) {

struct timespec ts;

ts.tv_sec = 1;

ts.tv_nsec = 0;



/*调用sigtimedwait()阻塞等待,等待时间1秒。*/

sigtimedwait(&sigset, &siginfo, &ts);



/* 测试是否有客户端发起连接请求,如果有则接受并把新建的描述符加入监控。*/

if(siginfo.si_fd == sock) {

new_sock = accept(sock, ...);

fcntl(new_sock , F_SETSIG, SIGRTMIN + 1);

fcntl(new_sock , F_SETOWN, getpid());

fcntl(new_sock , F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);

}else {

/* 对其它描述符发生的事件进行适当处理。*/

doReadAction(i);

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: