现在的位置: 首页 > 综合 > 正文

epoll服务器编程-demo

2012年09月28日 ⁄ 综合 ⁄ 共 2602字 ⁄ 字号 评论关闭

一个简单的EchoServer. 

在配置的网络地址上监听(也可以监听0.0.0.0)

  // create listen
  int
  init_listen_sock(int epsfd, unsigned short port)
  {
    std::vector<int> ip_list;
    if (!get_ipv4_addr(ip_list))
      return 1;

    for (int i = 0; i < ip_list.size(); i++)
      {
        int sfd = 0;
        if ((sfd = listen_on(ip_list[i], port)) < 0)
          return 1;
        int ipv4 = ip_list[i];
        unsigned char * pipv4 = (unsigned char *)&ipv4;
        LOG_INFO("listen on host: [%d.%d.%d.%d : %d]\n",
            pipv4[0],
            pipv4[1],
            pipv4[2],
            pipv4[3],
            port
            );
        if (ep_add(epsfd, sfd, true))
          return 1;
      }
    return 0;
  }

创建epoll句柄

  int ep_init()
  {
    return epoll_create(5);
  }

添加套接字到epoll队列

  int ep_add(int epfd, int sfd, bool is_listen_sock)
  {
    struct epoll_event evt;
    evt.events = EPOLLIN
                //| EPOLLOUT
                | EPOLLET
                  ;

    evt.data.ptr = malloc(sizeof(struct epoll_sock_t));
    epoll_sock_t * ptr = (epoll_sock_t *) evt.data.ptr;
    ptr->sock_fd = sfd;
    ptr->listen = is_listen_sock;

    int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &evt);
    return ret;
  }

从epoll队列中删除套接字

  int ep_del(int epfd, int sfd)
  {
    int ret = epoll_ctl(epfd, EPOLL_CTL_DEL, sfd, 0);
    return ret;
  }

关闭epoll句柄

  int ep_shutdown(int epfd)
  {
    close(epfd);
    return 0;
  }

在epoll队列上等待,如果有读写事件发生,就回调用户函数

  int
  ep_wait(int epfd, ep_wait_cb_t epw_cb, void * userdata)
  {
    struct epoll_event evts[EP_MAX_WAIT_NR] = { 0 };
    for (;;)
      {
        int nfds = 0; errno = 0;
        if (0 >= (nfds = epoll_wait(epfd, evts, EP_MAX_WAIT_NR, -1)) && errno != EINTR)
          {
            break;// stop
          }
        for (int i = 0; i < nfds; i++)
          {
            epw_cb(epfd, &evts[i], userdata);
          }
      }
  }

一个简单的启动线程

void * ep_thread(void * args)
{

  int epfd = 0;
  if ((epfd = ep_init()) <= 0)
    return 0;

  unsigned short port = 8000;
  if (init_listen_sock(epfd, port))
    {
      return 0;
    }

  void * userdata = 0;
  if (ep_wait(epfd, ep_event_callback, userdata))
    {
      return 0;
    }
  if (ep_shutdown(epfd))
    {
      return 0;
    };
  return (void *)0;
}

用户回调函数

int
ep_event_callback(int epfd, struct epoll_event * evt, void * userdata)
{
  epoll_sock_t * ptr = (epoll_sock_t *) (evt->data.ptr);

  if (evt->events & EPOLLIN)
    {
      printsockinfo(ptr->sock_fd);

      if (ptr->listen) // for listen socket
        {
          sockaddr_in csa;
          socklen_t csalen = sizeof(csa);
          int clientsfd = 0;
          errno = 0;
          while ((clientsfd = accept(ptr->sock_fd, (struct sockaddr *) &csa, &csalen)) > 0)
            {
              if (setnonblocking(clientsfd))
                {
                  LOG_ERROR("fail to set client socket to non-blocking.\n");
                  close(clientsfd);
                  continue;
                }

              if (ep_add(epfd, clientsfd, false))
                {
                LOG_ERROR("fail to add client socket to epoll.\n");
                close(clientsfd);
                continue;
                }
            }
          if (errno != EAGAIN && errno != EINTR)
            close(ptr->sock_fd);
        }
      else
        {
          errno = 0;
          char msg [0x200] = "";
          while (recv(ptr->sock_fd, msg, 0x200, 0) > 0)
            {
              tm_printstamp();
              LOG_INFO(" - %s \r\n", msg);
              fflush(stdout);
            }
          if (errno != EAGAIN && errno != EINTR)
            {
              close(ptr->sock_fd);
              LOG_ERROR("errno=[%d]\n", errno);
            }
        }
    }
  else if (evt->events & EPOLLERR)
    {
      LOG_INFO("catch an EPOLLERR, sockfd=[%d]. errno=[%d]\n", ptr->sock_fd, errno);
      close(ptr->sock_fd);
    }
  else
    {
      LOG_INFO("epoll events [%d] Ignored, sockfd = [%d].\n", evt->events, ptr->sock_fd);
    }

  return 0;
}

项目源文件,包括makefile.

http://hi.csdn.net/attachment/201112/30/0_1325239083n82M.gif

【上篇】
【下篇】

抱歉!评论已关闭.