50-使用 epoll 改写服务器
原创
©著作权归作者所有:来自51CTO博客作者mb63083a7dd962a的原创作品,请联系作者获取转载授权,否则将追究法律责任
使用 epoll 改写服务器,会让我们的程序变得更加简单、高效。
1. 程序路径
代码托管在 gitos 上,请使用下面的命令获取:
如果你已经 clone 过这个代码了,请使用 git pull 更新一下。本节程序所使用的程序路径是 unp/program/echo/multiplexing_epoll_server
。
2. 回忆 epoll 系列函数
主要有三个,分别是 epoll_create、epoll_ctl、epoll_wait. 有关 epoll 的具体用法,请参考《Linux 环境编程学习笔记》第十二章内容。
#include <sys/epoll.h>
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int
3. 使用 epoll 改写服务器
同样的,这里只贴出伪代码。
void server_routine() {
// ...
int epfd;
struct epoll_event evts[5]; // 接收 epoll_wait 的返回值
struct epoll_event ev;
listen(listenfd);
epfd = epoll_create(1); // 参数只要大于 0 就行了
// 添加 listenfd 到 epoll
ev.data.fd = listenfd;
ev.events = EPOLLIN;
epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &evt);
while(1) {
// 监听事件
nready = epoll_wait(epfd, evts, 5, 0);
for (i = 0; i < nready, ++i) {
// 查看是否有新的连接
if (evts[i].data.fd == listenfd && (evts[i].events & EPOLLIN)) {
sockfd = accept(listenfd);
ev.data.fd = sockfd;
ev.events = EPOLLIN;
// epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &evt);
// 此行原来有误,应该是添加 sockfd 而非 listenfd.感谢网友 Neymar 指出,修改如下:
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &evt);
}
// 与客户端交互数据
else if (evts[i].events & EPOLLIN) {
ret = doServer(evts[i].data.fd);
if (ret <= 0) {
// 客户端关闭,则将其从 epoll 中删除
epoll_ctl(epfd, EPOLL_CTL_DEL, evts[i].data.fd, NULL);
close(evts[i].data.fd);
4. 程序运行结果

图1 运行结果
5. 总结