Linux Epoll简单封装

1、单独起线程进行epoll时间的侦听

void epoll_wrapper::wait_event()
{
    struct epoll_event events[EPOLL_SIZE];
    while(true)
    {
        bzero(events,sizeof(events));
        int socketnumber = epoll_wait(m_epollfd,events,EPOLL_SIZE,-1);
        if(socketnumber < 0)
        {
            ExitAndPrintErr(__FILE__,__LINE__);
        }
        for(int i = 0;i < socketnumber;i++)
        {
            socket_handler * handler = (socket_handler *)events[i].data.ptr;
            int socketfd = handler->get_socket();
            if(exist_socket(socketfd))
            {
                pre_handler(handler, &(events[i]));
            }
            else
            {
                printf("not found socketfd = %d i = %d/n",socketfd,i);
            }
        }
    }
}

 

2、接收到事件后的预处理

void epoll_wrapper::pre_handler(socket_handler *  handler,struct epoll_event * event)
{
    int socketfd = handler->get_socket();
    unsigned char type = handler->get_type();
   
    if(type & HANDLER_TYPE_SERVER)
    {
        if(event->events & EPOLLIN)
        {
            while(true)
            {
                int clientSocket = accept(socketfd,NULL,NULL);
                if(clientSocket <= 0)
                {
                    if(EAGAIN == errno)
                        break;
                    PrintErr(__FILE__,__LINE__);
                }
                epoll_wrapper::set_nonblocking(clientSocket);
                printf("a client is connecting to the server fd = %d/n",clientSocket);
                handler->on_accept(clientSocket);
           }
        }
        if(event->events & EPOLLERR)
        {
            PrintErr(__FILE__,__LINE__);
            return ;
        }
    }
    if(type & HANDLER_TYPE_CLIENT)
    {
        if((event->events & EPOLLERR) && (event->events & EPOLLHUP) && (event->events & EPOLLIN))
        {
            printf("connect refused/n");
            PrintErr(__FILE__,__LINE__);
            handler->on_recv_and_send(SOCKET_EVENT_ERR,NULL,0);
            return ;
        }
        if(event->events & EPOLLERR)
        {
            PrintErr(__FILE__,__LINE__);
            handler->on_recv_and_send(SOCKET_EVENT_ERR,NULL,0);
            return ;
        }
        if((event->events & EPOLLHUP))
        {
            printf("connect successfully/n");
        }
        if(event->events & EPOLLIN)
        {
            Buff * t_buf = m_cache.get_freebuf();
            if(NULL == t_buf)
            {
                PrintErr(__FILE__,__LINE__,"mem cache is empty");
                return;
            }
            int max_buf_len = sizeof(Buff);
            int recv_count = 0;
            bzero(*t_buf,sizeof(Buff));
            while(true)
            {
                int bytecount = recv(socketfd,(char *)(*t_buf + recv_count) ,max_buf_len - recv_count,0);
                if(bytecount < 0)
                {
                    if(EAGAIN == errno)
                        break;

                    PrintErr(__FILE__,__LINE__);
                    handler->on_recv_and_send(SOCKET_EVENT_ERR,NULL,0);
                    m_cache.set_usedbuf(t_buf);
                    //close(event->data.fd);
                    return;
                }
                if(0 == bytecount)
                {
                    PrintErr(__FILE__,__LINE__);
                    printf("client closed  socketfd = %d/n",socketfd);
                    handler->on_recv_and_send(SOCKET_EVENT_SHUTDOWN,NULL,0);
                    m_cache.set_usedbuf(t_buf);
                    //close(event->data.fd);
                    return;
                }
                recv_count += bytecount;
            }
            handler->on_recv_and_send(SOCKET_EVENT_RECV,(char *)*t_buf,recv_count);
            m_cache.set_usedbuf(t_buf);
        }
        if(event->events & EPOLLOUT)
        {
            Buff * t_buf = handler->get_send_buf();
            unsigned int buf_len = handler->get_send_buf_len();
            int sendbytecount = send(socketfd,(char *)*t_buf,buf_len,0);
            if(sendbytecount < 0)
            {
                PrintErr(__FILE__,__LINE__);
                handler->on_recv_and_send(SOCKET_EVENT_ERR,NULL,0);
                //close(event->data.fd);
                return;
            }
            handler->on_recv_and_send(SOCKET_EVENT_SEND,NULL,0);
        }
    }
}

3、增加一个文件描述符到epfd中

int epoll_wrapper::add_socket(socket_handler * handler)
{
    int socketfd = handler->get_socket();
    struct epoll_event  epollevent;
    bzero(&epollevent,sizeof(epollevent));
    epollevent.data.ptr = handler;
    epollevent.events = EPOLLET | EPOLLIN | EPOLLERR;

    handler->set_epoll(this);

    AreaLock al(m_lockhandlers);
    map<int,socket_handler *>::iterator iter = m_handlers.find(socketfd);
    if(iter != m_handlers.end())
    {
        return -1;
    }
    pair<int,socket_handler *> mypair(socketfd,handler);
    m_handlers.insert(mypair);
   
    if(0 != epoll_ctl(m_epollfd,EPOLL_CTL_ADD,socketfd,&epollevent))
    {
        ExitAndPrintErr(__FILE__,__LINE__);
    }
    return 0;
}

(不知道重复增加会怎么样?)

4、修改一个文件描述符的侦听事件

int epoll_wrapper::send_data(socket_handler * handler)
{
    int socketfd = handler->get_socket();
    if(exist_socket(socketfd))
    {
        struct epoll_event event;
        bzero(&event,sizeof(event));
        event.data.ptr = handler;
        event.events = EPOLLOUT | EPOLLET | EPOLLIN | EPOLLERR;
       
        if(0 != epoll_ctl(m_epollfd,EPOLL_CTL_MOD,socketfd,&event))
        {
            ExitAndPrintErr(__FILE__,__LINE__);
        }
    }
    return 0;
}
5、从epfd中删除文件描述符

int epoll_wrapper::remove_socket(int socketfd)
{
    AreaLock al(m_lockhandlers);
    map_iter iter = m_handlers.find(socketfd);
    if(iter != m_handlers.end())
    {
        m_handlers.erase(iter);
    }
    if(0 != epoll_ctl(m_epollfd,EPOLL_CTL_DEL,socketfd,NULL))
    {
        ExitAndPrintErr(__FILE__,__LINE__);
    }
    return 0;
}

 

 完整下载地址(免费下载,欢迎指正):http://download.csdn.net/source/3315358

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值