免费注册 查看新帖 |

Chinaunix

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

epoll通讯编程问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-10-07 16:41 |只看该作者 |倒序浏览
本人在REHL5 下用epoll结合socket编了一个简单的数据收发的程序,但是运行到一定一会后便打印出错信息:

epollcomm.cpp-Send-358:异常事件,文件句柄:4发生错误,事件类型:EPOLLERR

本人的程序是全部代码如下:




  1. //打印
  2. #include <stdio.h>
  3. #define MYPRINTF(format,args...)    printf("%s-%s-%d:" format "\n",__FILE__,__FUNCTION__,__LINE__,##args)


  4. #include <sys/epoll.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <arpa/inet.h>
  8. #include <netinet/in.h>
  9. #include <string.h>
  10. #include <unistd.h>

  11. #include <pthread.h>
  12. #include <errno.h>
  13. #include <stdlib.h>



  14. //返回值定义
  15. #define EPOLL_SUCCEEDED            0    //成功
  16. #define EPOLL_FAILED            -1   //失败
  17. #define EPOLL_SEND_DATA_ERR     -2   //发送数据异常
  18. #define EPOLL_RECV_DATA_ERR     -3   //接受数据异常
  19. #define EPOLL_WAIT_ERR          -4   //epoll_wait 出错
  20. #define EPOLL_ALLOC_BUF_FAILED  -5   //分配内存失败
  21. #define EPOLL_DISTCONNECT       -6   //通信断联


  22. const char g_CommDataTag[2] = {0Xff,0Xee};
  23. #define COMMHEADERLEN 6    //2个标记,4个字节数据长度空间

  24. char        g_szServerIP[20];
  25. short       g_sServerPort;

  26. epoll_event ev1,ev2,event1s[10],event2s[10];
  27. int clientepfd;
  28. int serverepfd;

  29. int Listen()
  30. {
  31.     int         epfd;  //epoll句柄
  32.     epoll_event ev ,events;

  33.     int listen_sd;
  34.     int  iRet;
  35.     struct sockaddr_in sa_serv;   
  36.            
  37.     //构造 listen 套接字
  38.     listen_sd = socket( PF_INET, SOCK_STREAM, 0 );
  39.     if (-1 == listen_sd)
  40.     {
  41.         MYPRINTF("create listen socket failed");
  42.         return EPOLL_FAILED;
  43.     }   

  44.     //设置选项防止FIN_WAIT造成bind失败
  45.     bool val = true;
  46.     iRet = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, &val, 4);
  47.     if (iRet)
  48.     {
  49.         MYPRINTF("setsockopt(SO_REUSEADDR) failed");
  50.         return EPOLL_FAILED;
  51.     }

  52.    
  53.     //绑定IP
  54.     memset( &sa_serv, '\0', sizeof(sa_serv) );
  55.     sa_serv.sin_family      = AF_INET;
  56.     sa_serv.sin_addr.s_addr = inet_addr(g_szServerIP);//INADDR_ANY;
  57.     sa_serv.sin_port        = htons((unsigned short)g_sServerPort);          /* Server Port number */
  58.     iRet = bind( listen_sd, (struct sockaddr*)(&sa_serv), (socklen_t)sizeof (sa_serv) );
  59.     if (-1 == iRet)
  60.     {
  61.         MYPRINTF("server bind failed,可能该端口已被占用");
  62.         (void)close(listen_sd);
  63.         return EPOLL_FAILED;
  64.     }

  65. //use epoll
  66.     //生成用于epoll专用的文件描述符
  67.     epfd = epoll_create(65535);
  68.     if (-1 == epfd )
  69.     {
  70.         MYPRINTF("create epoll failed");
  71.         (void)close(listen_sd);
  72.         return EPOLL_FAILED;
  73.     }
  74.    
  75.     //加入epoll事件集合
  76.     ev.events = EPOLLIN ;
  77.     ev.data.fd = listen_sd;
  78.     if (epoll_ctl(epfd, EPOLL_CTL_ADD, listen_sd, &ev) < 0)
  79.     {
  80.         MYPRINTF("epoll set insertion error: fd=%d", listen_sd);
  81.         (void)close(listen_sd);
  82.         return EPOLL_FAILED;
  83.     }
  84. // end epoll

  85.     //监听连接
  86.     iRet = listen( listen_sd, 10 );
  87.     if (-1 == iRet)
  88.     {
  89.         MYPRINTF("server listen count %d failed", 10);
  90.         (void)close(listen_sd);
  91.         return EPOLL_FAILED;
  92.     }   
  93.         
  94.         while(true)
  95.         {
  96. // USE EPOLL   
  97.         iRet  = epoll_wait(epfd, &events, 1, -1);
  98.         if (iRet <= 0)
  99.         {
  100.                 MYPRINTF("epoll_wait error!-iRet:%d",iRet);
  101.             continue;
  102.         }
  103.         if(listen_sd == events.data.fd)
  104.         {
  105.                         int client_sd;
  106.                         socklen_t client_len;
  107.                         struct sockaddr_in sa_cli;       
  108.                         //
  109.                         client_len = (socklen_t)sizeof(sockaddr_in);
  110.                         client_sd = accept( listen_sd, (struct sockaddr*)&sa_cli, (socklen_t *)&client_len );
  111.                         if (-1 == client_sd)
  112.                         {
  113.                             MYPRINTF("accept failed-%d\n",errno);
  114.                             return EPOLL_FAILED;
  115.                         }                
  116.             else
  117.             {
  118.                                 //注册读事件
  119.                             ev.events = EPOLLIN;
  120.                             ev.data.fd = client_sd;
  121.                             if (epoll_ctl(serverepfd, EPOLL_CTL_ADD, client_sd, &ev) < 0)
  122.                             {
  123.                                     (void)close(client_sd);
  124.                                 MYPRINTF("epoll set insertion error: fd=%d", client_sd);
  125.                                 return EPOLL_FAILED;
  126.                             }                   
  127.                     MYPRINTF("Accept success");
  128.             }
  129.             
  130.         }
  131.         else
  132.         {
  133.                 MYPRINTF("event receive sd(%d) is wrong!",events.data.fd);
  134.                 continue;
  135.         }
  136. //end epoll
  137.                
  138.         }            
  139.     return EPOLL_SUCCEEDED;
  140. }


  141. void* ListenThread(void * vparam)
  142. {
  143.         if (EPOLL_FAILED == Listen())
  144.         {
  145.                 MYPRINTF("Listen error!");
  146.                 return NULL;
  147.         }       
  148.         return NULL;       
  149. }

  150. int Recv()
  151. {
  152.     serverepfd = epoll_create(65535);
  153.     if (-1 == serverepfd )
  154.     {
  155.         MYPRINTF("create epoll failed");
  156.         return EPOLL_FAILED;
  157.     }               
  158.        
  159.         pthread_t tListenThread;
  160.     pthread_attr_t attr;
  161.     pthread_attr_init(&attr);
  162.     pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
  163.    
  164.     if (pthread_create(&tListenThread,&attr,ListenThread,NULL))
  165.     {
  166.             MYPRINTF("Create thread ListenThread failed!");
  167.             return EPOLL_FAILED;
  168.     }           
  169.        
  170.        
  171.         char szRecvBuffer[100];
  172.         char szCommDataHeader[COMMHEADERLEN];
  173.         int nRet;
  174.         int nRecvDataLen;
  175.         while(1)
  176.         {       
  177.             int nfds  = epoll_wait(serverepfd, event1s, 10, -1);
  178.             if (nfds <= 0)
  179.             {
  180.                     MYPRINTF("epoll_wait error!nfds:%d",nfds);
  181.                 return EPOLL_WAIT_ERR;
  182.             }
  183.             MYPRINTF("nfds:%d",nfds);

  184.             for (int i = 0;i < nfds;i++)
  185.             {
  186.                     if (event1s[i].events&EPOLLIN)
  187.                     {
  188.                             //有读事件
  189.                                 nRet = recv(event1s[i].data.fd,szCommDataHeader,COMMHEADERLEN,0);
  190.                                 if (COMMHEADERLEN != nRet)
  191.                                 {
  192.                                         MYPRINTF("Recv Data header Error,data Len:%d-errno:%d",nRet,errno);
  193.                                 continue;
  194.                                 }       
  195.                             //比较数据头部标记
  196.                         if (memcmp(szCommDataHeader,g_CommDataTag,2))
  197.                         {
  198.                                 MYPRINTF("Comm Data Tag Error");
  199.                                 continue;                       
  200.                         }
  201.                                 
  202.                             memcpy(&nRecvDataLen,szCommDataHeader+2,4);//获取接收数据长度
  203.                             nRet = recv(event1s[i].data.fd,szRecvBuffer,nRecvDataLen,0);
  204.                                 if (COMMHEADERLEN == nRet)
  205.                                 {
  206.                                         MYPRINTF("Recv Data Error,data Len:%d-errno:%d",nRet,errno);
  207.                                 continue;
  208.                                 }           
  209.                             else
  210.                             {
  211.                                 MYPRINTF("Recv Data:%s-len:%d",szRecvBuffer,nRecvDataLen);
  212.                             }                            
  213.                         }
  214.                         else if (event1s[i].events&EPOLLERR)
  215.                         {
  216.                                 MYPRINTF("异常事件,文件句柄:%d发生错误,事件类型:EPOLLERR",event1s[i].data.fd);
  217.                         continue;                               
  218.                         }
  219.                         else if (event1s[i].events&EPOLLHUP)
  220.                         {
  221.                                 MYPRINTF("异常事件,文件句柄:%d被挂断,事件类型:EPOLLHUP",event1s[i].data.fd);
  222.                         continue;                               
  223.                         }
  224.                     else
  225.                     {
  226.                             MYPRINTF("异常事件,文件句柄:%d,事件类型:%u(EPOLLOUT:%u,EPOLLET:%u,EPOLHUP:%u,EPOLLERR:%u)-(ERROR->EBADF:%u,EFAULT:%u,EINVAL:%u,EINTR:%u)",
  227.                             event1s[i].data.fd,event1s[i].events,EPOLLOUT,EPOLLET,EPOLLHUP,EPOLLERR,EBADF,EFAULT,EINVAL,EINTR);
  228.                             continue;
  229.                     }
  230.                 }
  231.         }   
  232. }


  233. int Send()
  234. {
  235.        
  236.     clientepfd = epoll_create(65535);
  237.     if (-1 == clientepfd )
  238.     {
  239.         MYPRINTF("create epoll failed");
  240.         return EPOLL_FAILED;
  241.     }       
  242.         int nRet;
  243.     //******************* 连接服务器 *******************
  244.     //建立一个TCP套接口
  245.     int sd = socket( PF_INET, (int)SOCK_STREAM, 0 );
  246.     if (-1 == sd)
  247.     {
  248.         MYPRINTF("create client socket failed" );
  249.         return EPOLL_FAILED;
  250.     }

  251.     //初始化服务器地址结构
  252.     struct sockaddr_in addr;
  253.     memset( &addr, 0, sizeof(addr) );
  254.     addr.sin_family = AF_INET;
  255.     addr.sin_port   = htons((unsigned short)g_sServerPort);
  256.     addr.sin_addr.s_addr = inet_addr(g_szServerIP);

  257.     //和服务器建立连接
  258.     if ( -1 == connect(sd, (sockaddr *)&addr, sizeof(addr)) )
  259.     {
  260.         (void)close(sd);
  261.         return EPOLL_FAILED;
  262.     }
  263.     MYPRINTF("socket connect to %s:%d success, sd=%d\n", g_szServerIP,g_sServerPort,  sd);

  264.     //将连接关闭选项设为"立即关闭"
  265.     linger ling;
  266.     ling.l_onoff  = 1; // (在closesocket()调用,但是还有数据没发送完毕的时候容许逗留)
  267.     ling.l_linger = 0; // (容许逗留的时间为0秒),即不容许逗留
  268.     nRet = setsockopt(sd, SOL_SOCKET, SO_LINGER, (const char*)&ling, sizeof(ling));
  269.     if (0 != nRet)
  270.     {
  271.         MYPRINTF("set sock option no_linger failed");
  272.     }
  273.    
  274.         //注册写事件
  275.         epoll_event ev;
  276.     ev.events = EPOLLOUT;
  277.     ev.data.fd = sd;
  278.     if (epoll_ctl(clientepfd, EPOLL_CTL_ADD, sd, &ev) < 0)
  279.     {
  280.         MYPRINTF("epoll set error: fd=%d", sd);
  281.         return EPOLL_FAILED;
  282.     }
  283.    
  284.     char pTempData[100];
  285.     char szData[] =  "Hello World";
  286.     int nSendDataLen = strlen(szData);
  287.    
  288.     while(true)
  289.     {               
  290.                 memcpy(pTempData,g_CommDataTag,2);      //拷贝通信数据头部
  291.                 memcpy(pTempData+2,&nSendDataLen,4);    //拷贝发送数据长度
  292.                 memcpy(pTempData+COMMHEADERLEN,szData,nSendDataLen);//拷贝发送数据
  293.                
  294.                
  295.             int nfds  = epoll_wait(clientepfd,event2s, 10, 0);
  296.             if (nfds <= 0)
  297.             {
  298.                     usleep(100);
  299.                     //MYPRINTF("epoll_wait error!-iRet:%d",nfds);
  300.                 //return EPOLL_WAIT_ERR;
  301.             }
  302.             
  303.            for (int i = 0;i < nfds;i++)
  304.            {
  305.                            if (event2s[i].events&EPOLLOUT)
  306.                     {
  307.                             //有写事件            
  308.                             if(sd == event2s[i].data.fd)
  309.                             {
  310.                                     int iRet = send(sd,pTempData,nSendDataLen+COMMHEADERLEN,0);
  311.                                 if (-1 == iRet)
  312.                                 {
  313.                                         MYPRINTF("Send failed-errno:%d",errno);
  314.                                         return iRet;       
  315.                                 }
  316.                                 else
  317.                                 {
  318.                                         MYPRINTF("Send success");
  319.                                         continue;
  320.                                 }   
  321.                             }
  322.                             else
  323.                             {
  324.                                     MYPRINTF("event receive sd(%d) is wrong!",event2s[i].data.fd);
  325.                                     continue;
  326.                             }
  327.                             
  328.                         }
  329.                         else if (event2s[i].events&EPOLLERR)
  330.                         {
  331.                                 MYPRINTF("异常事件,文件句柄:%d发生错误,事件类型:EPOLLERR",event2s[i].data.fd);
  332.                         return EPOLL_DISTCONNECT;                               
  333.                         }
  334.                         else if (event2s[i].events&EPOLLHUP)
  335.                         {
  336.                                 MYPRINTF("异常事件,文件句柄:%d被挂断,事件类型:EPOLLHUP",event2s[i].data.fd);
  337.                         return EPOLL_DISTCONNECT;                               
  338.                         }               
  339.                     else
  340.                     {
  341.                             MYPRINTF("异常事件,文件句柄:%d,事件类型:%u(EPOLLIN:%u,EPOLLET:%u,EPOLHUP:%u,EPOLLERR:%u,EPOLLPRI:%u,EPOLLONESHOT:%u)-(ERROR->EBADF:%u,EFAULT:%u,EINVAL:%u,EINTR:%u)",
  342.                             event2s[i].data.fd,event2s[i].events,EPOLLIN,EPOLLET,
  343.                             EPOLLHUP,EPOLLERR,EPOLLPRI,EPOLLONESHOT,EBADF,EFAULT,EINVAL,EINTR);
  344.                             continue;
  345.                     }                                  
  346.                 }                        
  347.     }     
  348.            
  349. }


  350. void* ServerThread(void* vparam)
  351. {
  352.     Recv();
  353.            
  354.         return NULL;       
  355. }

  356. void* ClientThread(void* vparam)
  357. {
  358.         Send();
  359.        
  360.         MYPRINTF("Over");
  361.         return NULL;
  362. }

  363. int main(int argc,char* argv[])
  364. {
  365.         int nCmd;//1,启动服务端;  非1,启动客户端
  366.    
  367.         if (argc > 1)
  368.         {
  369.                 if (argc !=4)
  370.             {
  371.                     MYPRINTF("参数不对->%d",argc);
  372.                     return -1;
  373.             }
  374.                 nCmd = atoi(argv[1]);
  375.                 strcpy(g_szServerIP,argv[2]);
  376.                 g_sServerPort = atoi(argv[3]);
  377.         }
  378.         else
  379.         {
  380.                 strcpy(g_szServerIP,"127.0.0.1");
  381.                 g_sServerPort = 10000;
  382.                 nCmd = 1;
  383.         }
  384.         MYPRINTF("CMD:%d\n",nCmd);
  385.         MYPRINTF("IP:%s",g_szServerIP);
  386.         MYPRINTF("PORT:%d\n",g_sServerPort);
  387.        
  388.        
  389. pthread_t tServerThread,tClientThread;
  390.     pthread_attr_t attr;
  391.     pthread_attr_init(&attr);
  392.     pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
  393.    
  394.     if (1 == nCmd )
  395.     {
  396.         if (pthread_create(&tServerThread,&attr,ServerThread,NULL))
  397.         {
  398.                 MYPRINTF("Create thread failed!");
  399.                 return -1;
  400.         }       
  401.     }
  402.     else
  403.     {
  404.         if (pthread_create(&tClientThread,&attr,ClientThread,NULL))
  405.         {
  406.                 MYPRINTF("Create thread failed!");
  407.                 return -1;
  408.         }          
  409.     }
  410.       
  411.     pthread_attr_destroy(&attr);               
  412.        
  413.         sleep(100);
  414.         return 0;
  415. }

复制代码

[ 本帖最后由 leponylp 于 2007-10-11 22:58 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2007-10-07 16:42 |只看该作者
请各位帮忙看看,到底错在哪里。十分感激

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
3 [报告]
发表于 2007-10-07 16:49 |只看该作者
代码用 [code][/code] 括起来.

论坛徽章:
0
4 [报告]
发表于 2007-10-08 10:48 |只看该作者
对方关闭连接会有err事件返回,这时需要关闭对应的socket

论坛徽章:
0
5 [报告]
发表于 2007-10-11 22:30 |只看该作者
谢谢楼上给的建议。但是我的这个测试程序中,整个程序都是没有主动关闭连接的,整个过程是客户端发送数据,服务端接收数据啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP