epoll极简介绍
关于epoll的详细介绍,已经有较多文章可以参考,例如这篇文章介绍就比较详细:
http://blog.chinaunix.net/uid-24517549-id-4051156.htmlepoll编程的接口:
epoll_create
创建一个epoll内核对象,返回指向该对象的fdepoll_ctl
往epoll中添加、删除、修改需要监控的套接字epoll_wait
等待epoll中的套接字产生可读、可写、异常消息
使用epoll时有如下应该注意的地方:
- 确保被epoll的套接字必须是非阻塞的
- 读取可读的TCP套接字时,需要在循环中读取多次,直到返回值为-1且errno为EAGAIN为止,因为只有这种情况才说明可读的数据已经全部读完了
- 已经出错或断开连接的fd需要及时从epoll中删除掉,然后close fd
如下代码是使用epoll实现的多路复用TCP的简单Server及其测试客户端:
/******************************************************************************
* 文件名称:TestEpoll.cpp
* 文件描述:Epoll测试服务器端
* 创建日期:2015-04-09
* 作 者:casheywen
******************************************************************************/
#include <iostream>
using namespace std;
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#define LOG_ERR(fmt, args...) fprintf(stderr, "%d|"fmt"\n", __LINE__, ##args)
#define LOG_INFO(fmt, args...) fprintf(stdout, "%d|"fmt"\n", __LINE__, ##args)
int CreateListenFd(const char *pszIP, uint16_t usPort)
{
struct sockaddr_in stAddr;
stAddr.sin_family = AF_INET;
stAddr.sin_port = htons(usPort);
stAddr.sin_addr.s_addr = inet_addr(pszIP);
socklen_t nAddrLen = sizeof(struct sockaddr_in);
int iFd = socket(AF_INET, SOCK_STREAM, 0);
if (iFd < 0)
{
LOG_ERR("create socket fail: %s", strerror(errno));
return -1;
}
if (0 > bind(iFd, (struct sockaddr *)&stAddr, nAddrLen))
{
LOG_ERR("bind fail: %s", strerror(errno));
return -1;
}
if (0 > listen(iFd, 64))
{
LOG_E