Chinaunix首页 | 论坛 | 博客
  • 博客访问: 444731
  • 博文数量: 89
  • 博客积分: 2713
  • 博客等级: 少校
  • 技术积分: 938
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-18 21:19
个人简介

为了成为自由自在的人而奋斗!

文章分类

全部博文(89)

文章存档

2016年(5)

2015年(9)

2014年(2)

2013年(10)

2012年(1)

2011年(30)

2010年(32)

分类: C/C++

2014-12-23 12:57:17

epoll的原理网上很多, 这边实现一个TCP server,备忘, 后续可以快速编程 呵呵
#include
#include
#include
#include
#include

#include
#include
#include
#include
#include
#include
#include
#include
#include

/*

struct epoll_event
{
  uint32_t events;    
  epoll_data_t data;    
} __attribute__ ((__packed__));

//union
typedef union epoll_data
{
  void *ptr;
  int fd;
  uint32_t u32;
  uint64_t u64;
} epoll_data_t;

*/

typedef struct epoll_event epoll_event_t;

using namespace std;

#define LISTEN_PORT (6666) //监听端口
#define MAXEVENT_NUM (1024) //最大监听数


//设置为非阻塞socket
int set_nonblock(int fd)
{
 int flags = fcntl(fd, F_GETFL, 0);
 if (flags == -1)
  return -1;

 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}


int OnRecv(epoll_event_t *pEv)
{
    if (pEv->events & EPOLLIN)
    {
        // Recv
        int Recvlen = 0;
        char buf[256];
        for (;;)
        {
            Recvlen = recv(pEv->data.fd, buf, 256, 0);
            if (Recvlen > 0)
            {
                cout << "recv len "<< Recvlen << endl;
            }
            else
            {
                if ((Recvlen < 0) && (errno == EWOULDBLOCK || errno == EAGAIN))
                {
                    return 0; // Next time to read
                }

              
    // TODO: 从epoll队列删除
                return -1;
            }
        }
       
    }
 
 return 0;
}


//新连接, 设置为非阻塞,加入监听
void OnAccept(int newFd, int EpollFd)
{
    epoll_event_t ev;
    ev.events= EPOLLIN | EPOLLOUT | EPOLLET;
    ev.data.fd = newFd;

    set_nonblock(newFd);
   
    if( epoll_ctl(EpollFd, EPOLL_CTL_ADD, newFd, &ev)==-1)
    {
        return ;
    }

    cout << "accept "< }

 

//处理线程函数
void *ThreadRun(void *argv)
{
    epoll_event_t *m_events = (epoll_event_t*)malloc(sizeof(epoll_event_t) * MAXEVENT_NUM);
 
 //创建epoll描述字
    int epollFd = epoll_create(MAXEVENT_NUM);
 
 //监听端口socket
    int InputFd = *((int*)argv);
    if( set_nonblock(InputFd) )
    {
        return NULL;
    }

    cout << "Run InputFd"<    
    epoll_event_t ev;
    ev.events= EPOLLIN | EPOLLOUT | EPOLLET;
    ev.data.fd = InputFd;
 //加入epoll队列
    if( epoll_ctl(epollFd, EPOLL_CTL_ADD, InputFd, &ev)==-1)
    {
        cout << "liste error xxx" <         return NULL;
    }
   
    if (listen(InputFd, 5))
    {
        return NULL;
    }

    while (1)
    {
        int ret = epoll_wait(epollFd, m_events,MAXEVENT_NUM, 5000);
        if (ret > 0)
        {
            for (int i = 0; i < ret; ++i)
            {
                if (m_events[i].data.fd == InputFd)//accept
                {
                    cout << "liste error 1" <                     struct sockaddr_in addr;
                    while (1)
                    {
                       
                        cout << "liste error 2" <                         socklen_t addrlen = sizeof(addr);
                        int so = accept(ev.data.fd, (sockaddr*) &addr, &addrlen);
                        if (-1 != so)
                        {
                            OnAccept(so, epollFd);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else
                {
                    if (OnRecv(&m_events[i]) == -1)
     {
      epoll_event_t ev;
      ev.data.fd=m_events[i].data.fd;
      ev.events=0;
      
      if( epoll_ctl(epollFd, EPOLL_CTL_DEL, m_events[i].data.fd, &ev)==-1)
      {
       cout << ("epoll_ctl(EPOLL_CTL_DEL) failed") <       }
      else
      {
       cout<<"leave "<       }
      close(m_events[i].data.fd);
     }
                }
            }
        }
    }

    return NULL;   
}


int main()
{
    int fd = -1;
    int flag;
    int len = sizeof(int);
   
    fd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == fd)
    {       
        return -1;
    }

    struct sockaddr_in m_addr;
    m_addr.sin_addr.s_addr = INADDR_ANY ;
    m_addr.sin_family = AF_INET;
    m_addr.sin_port = htons(LISTEN_PORT);

    if (-1 == setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, len))
    {
        return -1;
    }

    if (-1 == bind(fd,(sockaddr*)&m_addr,sizeof(m_addr)))
    {
        return -1;
    }

    pthread_t thread;
    pthread_create(&(thread), NULL,  ThreadRun, (void*)&fd);
    cout << "create "<

    pthread_join(thread, NULL);

    return 0;
}

 

阅读(2286) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~