免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 8963 | 回复: 7
打印 上一主题 下一主题

epoll_ctl(EpollFd, EPOLL_CTL_ADD, Socket, &ev) 报错 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-09-29 15:00 |只看该作者 |倒序浏览
int Epollfd;
struct epoll_event ev, events[10000];

CPUB_EpollServer::CPUB_EpollServer()
{
        pthread_mutex_init(&EPollMutex, NULL);
        Epollfd = epoll_create(10000);
}

CPUB_EpollServer::~CPUB_EpollServer()
{
        
        
}

/*
*--------------------------------------------------------------------
*
*  Functionname: int CPUB_EpollServer::Epoll_Wait
*
*    Parameters: in) int Socket: socket 描述符
*                in) int *EventSocket: 有事件的socket
*
*   Description: 等待注册的socket事件的产生
*
*        Return: FALSE
*
*--------------------------------------------------------------------
*/
int CPUB_EpollServer::Epoll_Wait(int Socket, int *EventSocket, int Currfds, int Time )
{
  int ActiveFd = 0;

        while(1)
        {
                ActiveFd = epoll_wait(Epollfd, events, Currfds, Time);
                if( ActiveFd <= 0 )
    {
      continue;
    }
    for( int i = 0; i < ActiveFd; ++i )
    {
      if( events.data.fd == Socket)
      {
              *EventSocket = Socket;
              return Socket;
                  }
                  else if( events.events&EPOLLERR )
                  {
                          *EventSocket = events.data.fd;
                          return EPOLLERR;
                  }
                  else if( events.events&EPOLLHUP )
                  {
                          *EventSocket = events.data.fd;
                          return EPOLLHUP;
                  }
                  else if( events.events&EPOLLIN )
                  {
                         *EventSocket = events.data.fd;
                          return EPOLLIN;
                  }
                }
        } //end while
        return FALSE;
}


/*
*--------------------------------------------------------------------
*
*  Functionname: int CPUB_EpollServer::Epoll_CtlADD
*
*    Parameters: in) socket: Socket 描述符
*
*   Description: 将socket描述符注册事件并加入到Epoll集合
*
*        Return: 成功 TRUE  失败 FALSE
*
*--------------------------------------------------------------------
*/
int CPUB_EpollServer::Epoll_CtlADD(int Socket)
{
        pthread_mutex_lock(&EPollMutex);
        //struct epoll_event ev;
        ev.data.fd = Socket;
  ev.events = EPOLLERR|EPOLLIN|EPOLLHUP;

  if (epoll_ctl(Epollfd, EPOLL_CTL_ADD, Socket, &ev) < 0)
  {
          printf("epoll add failed errno = %d  str = %s\n", errno, strerror(errno));
          pthread_mutex_unlock(&EPollMutex);
          return FALSE;
  }
  pthread_mutex_unlock(&EPollMutex);
  return TRUE;
}

/*
*--------------------------------------------------------------------
*
*  Functionname: int CPUB_EpollServer::Epoll_CtlDEL(int Socket)
*
*    Parameters: in) socket: Socket 描述符
*
*   Description: 将Socket描述符从Epoll事件集合中删除
*
*        Return: non
*
*--------------------------------------------------------------------
*/
void CPUB_EpollServer::Epoll_CtlDEL(int Socket)
{
        pthread_mutex_lock(&EPollMutex);
        //struct epoll_event ev;

  epoll_ctl(Epollfd, EPOLL_CTL_DEL, Socket, &ev);
  pthread_mutex_unlock(&EPollMutex);
}


我是一个线程调用 CPUB_EpollServer::Epoll_Wait(int Socket, int *EventSocket, int Currfds, int Time )


有可读事件,socket 加入到一个链表中,然后 调用 CPUB_EpollServer::Epoll_CtlDEL(int Socket)

其他某个线程取到socket 后并接收,接收完后调用 int CPUB_EpollServer::Epoll_CtlADD(int Socket)

但是int CPUB_EpollServer::Epoll_CtlADD(int Socket)总是 报错  即 < 0
if (epoll_ctl(Epollfd, EPOLL_CTL_ADD, Socket, &ev) < 0)
  {
          printf("epoll add failed errno = %d  str = %s\n", errno, strerror(errno));
          pthread_mutex_unlock(&EPollMutex);
          return FALSE;
  }

epoll add failed errno = 17  str = File exists

怎么回事 ? 怎么避免


[ 本帖最后由 齐得龙强更强 于 2009-9-29 15:46 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-09-29 15:32 |只看该作者
自己顶

论坛徽章:
0
3 [报告]
发表于 2009-09-29 16:38 |只看该作者

论坛徽章:
0
4 [报告]
发表于 2009-09-29 17:23 |只看该作者
继续 等待  期待高手  们 不要 出去玩

论坛徽章:
0
5 [报告]
发表于 2009-09-29 18:00 |只看该作者
不太理解lz的流程设计...

论坛徽章:
0
6 [报告]
发表于 2009-09-29 20:52 |只看该作者
原帖由 5毛党党员 于 2009-9-29 18:00 发表
不太理解lz的流程设计...


我在 main 函数 类 的全局区 实例类:CPUB_EpollServer m_EpollServer;  其他类的全局区: extern  CPUB_EpollServer m_EpollServer;

服务器 socket(), bind(), listen() , 然后把创建的socket注册到epoll中,即调用m_EpollServer.Epoll_CtlADD(int Socket);

m_EpollServer.Epoll_CtlADD( SOCKET );//SOCKET服务端监听的socket
   while(1)
   {
        Ret = m_EpollServer.Epoll_Wait(SOCKET, &EventSocket, Currfds, 100 );
       if( Ret ==  SOCKET)
       {
           while(1)
           {
              ClientSocket = m_SocketLib.Accept(SOCKET);
              if( ClientSocket == FALSE )
              {
                   break;
              }
              m_SocketLib.SetNonBlocking( ClientSocket );
              m_EpollServer.Epoll_CtlADD(ClientSocket);//有新的连接 注册事件
              Currfds++;
            }
        }
        else if( Ret == EPOLLERR )
        {
                  m_EpollServer.Epoll_CtlDEL( EventSocket );
                  Currfds--;
                  continue;
         }
         else if( Ret == EPOLLHUP )
         {
                  m_EpollServer.Epoll_CtlDEL( EventSocket);
                  Currfds--;
                  continue;
        }
        else if( Ret == EPOLLIN )
        {
                  //有可读事件, 将该socket加入到list中,并将socket从epoll集合中删除
                  m_VectorServer.AddToList(EventSocket );
                  m_EpollServer.Epoll_CtlDEL( EventSocket );
                  continue;
        }
      } //end while

其他线程从list中取socket 并接收,接收完后,再调用m_EpollServer.Epoll_CtlADD(ClientSocket);对socket 注册事件

不知道我说明白了没有

[ 本帖最后由 齐得龙强更强 于 2009-9-29 20:54 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2009-09-30 11:18 |只看该作者
打印一下epoll_ctl(Epollfd, EPOLL_CTL_DEL, Socket, &ev);的返回值

论坛徽章:
0
8 [报告]
发表于 2009-09-30 11:31 |只看该作者
两点建议:
1. 你的问题在于连续三个步骤add->del->add会失败, 先把问题最小化, 写个测试代码, 看看问题到底在那里
2. 这个方法似乎不大好, 你的需求应该用oneshot模式来实现, 而不是add->del->add

  1. EPOLLONESHOT (since kernel 2.6.2)
  2.               Sets  the  one-shot  behaviour for the associated file descriptor.  This means that after an event is pulled out with epoll_wait(2) the associated
  3.               file descriptor is internally disabled and no other events will be reported  by  the  epoll  interface.  The  user  must  call  epoll_ctl(2)  with
  4.               EPOLL_CTL_MOD to re-enable the file descriptor with a new event mask.
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP