epoll常用函数

先声明,本文涉及到的知识是之前搜集到的,现在整理出来分享大家,虽然打上原创的tag,但还是向原创致敬!如果涉及到侵权的问题,请联系我,我会及时更改!


epoll用到的所有函数都是在头文件sys/epoll.h中声明


1、int epoll_create(int size);
   生成一个 Epoll 专用的文件描述符,其实是申请一个内核空间,用来存放你想关注的 socket fd 上是否发生以及发生了什么事件。 size 就是你在这个 Epoll fd 上能关注的最大 socket fd 数,大小自定,只要内存足够。
        
2、int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event );
   控制某个 Epoll 文件描述符上的事件:注册、修改、删除。其中参数 epfd 是 epoll_create() 创建 Epoll 专用的文件描述符。相对于 select 模型中的 FD_SET 和 FD_CLR 宏。
参数说明:
    op:EPOLL_CTL_ADD(增加)     EPOLL_CTL_MOD(修改)   EPOLL_CTL_DEL(删除)


3、int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout);
参数说明:
epfd: 由 epoll_create() 生成的 Epoll 专用的文件描述符;
epoll_event: 用于回传代处理事件的数组;
maxevents: 每次能处理的事件数;
timeout: 等待 I/O 事件发生的超时值,单位 ms
返回发生事件数。


        
下面给出实例代码
/* 实现功能:通过epoll, 处理多个socket 
 * 监听一个端口,监听到有链接时,添加到epoll_event 
 */  
#include "select.h"  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/socket.h>  
#include <poll.h>  
#include <sys/epoll.h>  
#include <sys/time.h>  
#include <netinet/in.h>  
  
typedef struct _CLIENT{  
    int fd;  
    struct sockaddr_in addr; /* client's address information */  
} CLIENT;  
  
#define MYPORT 59000  
  
//最多处理的connect  
#define MAX_EVENTS 500  
  
//当前的连接数  
int currentClient = 0;   
  
//数据接受 buf  
#define REVLEN 10  
char recvBuf[REVLEN];  
  
//EPOLL相关   
//epoll描述符  
int epollfd;  
//事件数组  
struct epoll_event eventList[MAX_EVENTS];  
  
void AcceptConn(int srvfd);  
void RecvData(int fd);  
  
int main()  
{  
    int i, ret, sinSize;  
    int recvLen = 0;  
    fd_set readfds, writefds;  
    int sockListen, sockSvr, sockMax;  
    int timeout;  
    struct sockaddr_in server_addr;  
    struct sockaddr_in client_addr;  
      
    //socket  
    if((sockListen=socket(AF_INET, SOCK_STREAM, 0)) < 0)  
    {  
        printf("socket error\n");  
        return -1;  
    }  
      
    bzero(&server_addr, sizeof(server_addr));  
    server_addr.sin_family  =  AF_INET;  
    server_addr.sin_port = htons(MYPORT);  
    server_addr.sin_addr.s_addr  =  htonl(INADDR_ANY);   
      
    //bind  
    if(bind(sockListen, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)  
    {  
        printf("bind error\n");  
        return -1;  
    }  
      
    //listen  
    if(listen(sockListen, 5) < 0)  
    {  
        printf("listen error\n");  
        return -1;  
    }  
      
    //1. epoll 初始化  
    epollfd = epoll_create(MAX_EVENTS);  
    struct epoll_event event;  
    event.events = EPOLLIN|EPOLLET;  
    event.data.fd = sockListen;  
      
    //2. epoll_ctrl  
    if(epoll_ctl(epollfd, EPOLL_CTL_ADD, sockListen, &event) < 0)  
    {  
        printf("epoll add fail : fd = %d\n", sockListen);  
        return -1;  
    }  
      
    //epoll  
    while(1)  
    {  
        timeout=3000;                  
        //3. epoll_wait  
        int ret = epoll_wait(epollfd, eventList, MAX_EVENTS, timeout);  
          
        if(ret < 0)  
        {  
            printf("epoll error\n");  
            break;  
        }  
        else if(ret == 0)  
        {  
            printf("timeout ...\n");  
            continue;  
        }  
          
        //直接获取了事件数量,给出了活动的流,这里是和poll区别的关键  
        int n = 0;  
        for(n=0; n<ret; n++)  
        {  
            //错误退出  
            if ((eventList[n].events & EPOLLERR) ||  
                (eventList[n].events & EPOLLHUP) ||  
                !(eventList[n].events & EPOLLIN))  
            {  
              printf ( "epoll error\n");  
              close (eventList[n].data.fd);  
              return -1;  
            }  
              
            if (eventList[n].data.fd == sockListen)  
            {  
                AcceptConn(sockListen);  
          
            }else{  
                RecvData(eventList[n].data.fd);  
                //不删除  
             //   epoll_ctl(epollfd, EPOLL_CTL_DEL, pEvent->data.fd, pEvent);  
            }  
        }  
    }  
      
    close(epollfd);  
    close(sockListen);  
      
    printf("test\n");  
    return 0;  
}  
  
/************************************************** 
函数名:AcceptConn 
功能:接受客户端的链接 
参数:srvfd:监听SOCKET 
***************************************************/  
void AcceptConn(int srvfd)  
{  
    struct sockaddr_in sin;  
    socklen_t len = sizeof(struct sockaddr_in);  
    bzero(&sin, len);  
  
    int confd = accept(srvfd, (struct sockaddr*)&sin, &len);  
  
    if (confd < 0)  
    {  
       printf("bad accept\n");  
       return;  
    }else  
    {  
        printf("Accept Connection: %d", confd);  
    }  
  
    //setnonblocking(confd);  
  
    //4. epoll_wait  
    //将新建立的连接添加到EPOLL的监听中  
    struct epoll_event event;  
    event.data.fd = confd;  
    event.events =  EPOLLIN|EPOLLET;  
    epoll_ctl(epollfd, EPOLL_CTL_ADD, confd, &event);  
}  
  
//读取数据  
void RecvData(int fd)  
{  
    int ret;  
    int recvLen = 0;  
      
    memset(recvBuf, 0, REVLEN);  
    printf("RecvData function\n");  
      
    if(recvLen != REVLEN)  
    {  
        while(1)  
        {  
            //recv数据  
            ret = recv(fd, (char *)recvBuf+recvLen, REVLEN-recvLen, 0);  
            if(ret == 0)  
            {  
                recvLen = 0;  
                break;  
            }  
            else if(ret < 0)  
            {  
                recvLen = 0;  
                break;  
            }  
            //数据接受正常  
            recvLen = recvLen+ret;  
            if(recvLen<REVLEN)  
            {  
                continue;  
            }  
            else  
            {  
                //数据接受完毕  
                printf("buf = %s\n",  recvBuf);  
                recvLen = 0;  
                break;  
            }  
        }  
    }  
  
    printf("content is %s", recvBuf);  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值