- 论坛徽章:
- 0
|
本人在REHL5 下用epoll结合socket编了一个简单的数据收发的程序,但是运行到一定一会后便打印出错信息:
epollcomm.cpp-Send-358:异常事件,文件句柄:4发生错误,事件类型:EPOLLERR
本人的程序是全部代码如下:
- //打印
- #include <stdio.h>
- #define MYPRINTF(format,args...) printf("%s-%s-%d:" format "\n",__FILE__,__FUNCTION__,__LINE__,##args)
- #include <sys/epoll.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <string.h>
- #include <unistd.h>
- #include <pthread.h>
- #include <errno.h>
- #include <stdlib.h>
- //返回值定义
- #define EPOLL_SUCCEEDED 0 //成功
- #define EPOLL_FAILED -1 //失败
- #define EPOLL_SEND_DATA_ERR -2 //发送数据异常
- #define EPOLL_RECV_DATA_ERR -3 //接受数据异常
- #define EPOLL_WAIT_ERR -4 //epoll_wait 出错
- #define EPOLL_ALLOC_BUF_FAILED -5 //分配内存失败
- #define EPOLL_DISTCONNECT -6 //通信断联
- const char g_CommDataTag[2] = {0Xff,0Xee};
- #define COMMHEADERLEN 6 //2个标记,4个字节数据长度空间
- char g_szServerIP[20];
- short g_sServerPort;
- epoll_event ev1,ev2,event1s[10],event2s[10];
- int clientepfd;
- int serverepfd;
- int Listen()
- {
- int epfd; //epoll句柄
- epoll_event ev ,events;
-
- int listen_sd;
- int iRet;
- struct sockaddr_in sa_serv;
-
- //构造 listen 套接字
- listen_sd = socket( PF_INET, SOCK_STREAM, 0 );
- if (-1 == listen_sd)
- {
- MYPRINTF("create listen socket failed");
- return EPOLL_FAILED;
- }
- //设置选项防止FIN_WAIT造成bind失败
- bool val = true;
- iRet = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, &val, 4);
- if (iRet)
- {
- MYPRINTF("setsockopt(SO_REUSEADDR) failed");
- return EPOLL_FAILED;
- }
-
- //绑定IP
- memset( &sa_serv, '\0', sizeof(sa_serv) );
- sa_serv.sin_family = AF_INET;
- sa_serv.sin_addr.s_addr = inet_addr(g_szServerIP);//INADDR_ANY;
- sa_serv.sin_port = htons((unsigned short)g_sServerPort); /* Server Port number */
- iRet = bind( listen_sd, (struct sockaddr*)(&sa_serv), (socklen_t)sizeof (sa_serv) );
- if (-1 == iRet)
- {
- MYPRINTF("server bind failed,可能该端口已被占用");
- (void)close(listen_sd);
- return EPOLL_FAILED;
- }
- //use epoll
- //生成用于epoll专用的文件描述符
- epfd = epoll_create(65535);
- if (-1 == epfd )
- {
- MYPRINTF("create epoll failed");
- (void)close(listen_sd);
- return EPOLL_FAILED;
- }
-
- //加入epoll事件集合
- ev.events = EPOLLIN ;
- ev.data.fd = listen_sd;
- if (epoll_ctl(epfd, EPOLL_CTL_ADD, listen_sd, &ev) < 0)
- {
- MYPRINTF("epoll set insertion error: fd=%d", listen_sd);
- (void)close(listen_sd);
- return EPOLL_FAILED;
- }
- // end epoll
- //监听连接
- iRet = listen( listen_sd, 10 );
- if (-1 == iRet)
- {
- MYPRINTF("server listen count %d failed", 10);
- (void)close(listen_sd);
- return EPOLL_FAILED;
- }
-
- while(true)
- {
- // USE EPOLL
- iRet = epoll_wait(epfd, &events, 1, -1);
- if (iRet <= 0)
- {
- MYPRINTF("epoll_wait error!-iRet:%d",iRet);
- continue;
- }
- if(listen_sd == events.data.fd)
- {
- int client_sd;
- socklen_t client_len;
- struct sockaddr_in sa_cli;
- //
- client_len = (socklen_t)sizeof(sockaddr_in);
- client_sd = accept( listen_sd, (struct sockaddr*)&sa_cli, (socklen_t *)&client_len );
- if (-1 == client_sd)
- {
- MYPRINTF("accept failed-%d\n",errno);
- return EPOLL_FAILED;
- }
- else
- {
- //注册读事件
- ev.events = EPOLLIN;
- ev.data.fd = client_sd;
- if (epoll_ctl(serverepfd, EPOLL_CTL_ADD, client_sd, &ev) < 0)
- {
- (void)close(client_sd);
- MYPRINTF("epoll set insertion error: fd=%d", client_sd);
- return EPOLL_FAILED;
- }
- MYPRINTF("Accept success");
- }
-
- }
- else
- {
- MYPRINTF("event receive sd(%d) is wrong!",events.data.fd);
- continue;
- }
- //end epoll
-
- }
- return EPOLL_SUCCEEDED;
- }
- void* ListenThread(void * vparam)
- {
- if (EPOLL_FAILED == Listen())
- {
- MYPRINTF("Listen error!");
- return NULL;
- }
- return NULL;
- }
- int Recv()
- {
- serverepfd = epoll_create(65535);
- if (-1 == serverepfd )
- {
- MYPRINTF("create epoll failed");
- return EPOLL_FAILED;
- }
-
- pthread_t tListenThread;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
-
- if (pthread_create(&tListenThread,&attr,ListenThread,NULL))
- {
- MYPRINTF("Create thread ListenThread failed!");
- return EPOLL_FAILED;
- }
-
-
- char szRecvBuffer[100];
- char szCommDataHeader[COMMHEADERLEN];
- int nRet;
- int nRecvDataLen;
- while(1)
- {
- int nfds = epoll_wait(serverepfd, event1s, 10, -1);
- if (nfds <= 0)
- {
- MYPRINTF("epoll_wait error!nfds:%d",nfds);
- return EPOLL_WAIT_ERR;
- }
- MYPRINTF("nfds:%d",nfds);
- for (int i = 0;i < nfds;i++)
- {
- if (event1s[i].events&EPOLLIN)
- {
- //有读事件
- nRet = recv(event1s[i].data.fd,szCommDataHeader,COMMHEADERLEN,0);
- if (COMMHEADERLEN != nRet)
- {
- MYPRINTF("Recv Data header Error,data Len:%d-errno:%d",nRet,errno);
- continue;
- }
- //比较数据头部标记
- if (memcmp(szCommDataHeader,g_CommDataTag,2))
- {
- MYPRINTF("Comm Data Tag Error");
- continue;
- }
-
- memcpy(&nRecvDataLen,szCommDataHeader+2,4);//获取接收数据长度
- nRet = recv(event1s[i].data.fd,szRecvBuffer,nRecvDataLen,0);
- if (COMMHEADERLEN == nRet)
- {
- MYPRINTF("Recv Data Error,data Len:%d-errno:%d",nRet,errno);
- continue;
- }
- else
- {
- MYPRINTF("Recv Data:%s-len:%d",szRecvBuffer,nRecvDataLen);
- }
- }
- else if (event1s[i].events&EPOLLERR)
- {
- MYPRINTF("异常事件,文件句柄:%d发生错误,事件类型:EPOLLERR",event1s[i].data.fd);
- continue;
- }
- else if (event1s[i].events&EPOLLHUP)
- {
- MYPRINTF("异常事件,文件句柄:%d被挂断,事件类型:EPOLLHUP",event1s[i].data.fd);
- continue;
- }
- else
- {
- MYPRINTF("异常事件,文件句柄:%d,事件类型:%u(EPOLLOUT:%u,EPOLLET:%u,EPOLHUP:%u,EPOLLERR:%u)-(ERROR->EBADF:%u,EFAULT:%u,EINVAL:%u,EINTR:%u)",
- event1s[i].data.fd,event1s[i].events,EPOLLOUT,EPOLLET,EPOLLHUP,EPOLLERR,EBADF,EFAULT,EINVAL,EINTR);
- continue;
- }
- }
- }
- }
- int Send()
- {
-
- clientepfd = epoll_create(65535);
- if (-1 == clientepfd )
- {
- MYPRINTF("create epoll failed");
- return EPOLL_FAILED;
- }
- int nRet;
- //******************* 连接服务器 *******************
- //建立一个TCP套接口
- int sd = socket( PF_INET, (int)SOCK_STREAM, 0 );
- if (-1 == sd)
- {
- MYPRINTF("create client socket failed" );
- return EPOLL_FAILED;
- }
- //初始化服务器地址结构
- struct sockaddr_in addr;
- memset( &addr, 0, sizeof(addr) );
- addr.sin_family = AF_INET;
- addr.sin_port = htons((unsigned short)g_sServerPort);
- addr.sin_addr.s_addr = inet_addr(g_szServerIP);
- //和服务器建立连接
- if ( -1 == connect(sd, (sockaddr *)&addr, sizeof(addr)) )
- {
- (void)close(sd);
- return EPOLL_FAILED;
- }
- MYPRINTF("socket connect to %s:%d success, sd=%d\n", g_szServerIP,g_sServerPort, sd);
- //将连接关闭选项设为"立即关闭"
- linger ling;
- ling.l_onoff = 1; // (在closesocket()调用,但是还有数据没发送完毕的时候容许逗留)
- ling.l_linger = 0; // (容许逗留的时间为0秒),即不容许逗留
- nRet = setsockopt(sd, SOL_SOCKET, SO_LINGER, (const char*)&ling, sizeof(ling));
- if (0 != nRet)
- {
- MYPRINTF("set sock option no_linger failed");
- }
-
- //注册写事件
- epoll_event ev;
- ev.events = EPOLLOUT;
- ev.data.fd = sd;
- if (epoll_ctl(clientepfd, EPOLL_CTL_ADD, sd, &ev) < 0)
- {
- MYPRINTF("epoll set error: fd=%d", sd);
- return EPOLL_FAILED;
- }
-
- char pTempData[100];
- char szData[] = "Hello World";
- int nSendDataLen = strlen(szData);
-
- while(true)
- {
- memcpy(pTempData,g_CommDataTag,2); //拷贝通信数据头部
- memcpy(pTempData+2,&nSendDataLen,4); //拷贝发送数据长度
- memcpy(pTempData+COMMHEADERLEN,szData,nSendDataLen);//拷贝发送数据
-
-
- int nfds = epoll_wait(clientepfd,event2s, 10, 0);
- if (nfds <= 0)
- {
- usleep(100);
- //MYPRINTF("epoll_wait error!-iRet:%d",nfds);
- //return EPOLL_WAIT_ERR;
- }
-
- for (int i = 0;i < nfds;i++)
- {
- if (event2s[i].events&EPOLLOUT)
- {
- //有写事件
- if(sd == event2s[i].data.fd)
- {
- int iRet = send(sd,pTempData,nSendDataLen+COMMHEADERLEN,0);
- if (-1 == iRet)
- {
- MYPRINTF("Send failed-errno:%d",errno);
- return iRet;
- }
- else
- {
- MYPRINTF("Send success");
- continue;
- }
- }
- else
- {
- MYPRINTF("event receive sd(%d) is wrong!",event2s[i].data.fd);
- continue;
- }
-
- }
- else if (event2s[i].events&EPOLLERR)
- {
- MYPRINTF("异常事件,文件句柄:%d发生错误,事件类型:EPOLLERR",event2s[i].data.fd);
- return EPOLL_DISTCONNECT;
- }
- else if (event2s[i].events&EPOLLHUP)
- {
- MYPRINTF("异常事件,文件句柄:%d被挂断,事件类型:EPOLLHUP",event2s[i].data.fd);
- return EPOLL_DISTCONNECT;
- }
- else
- {
- MYPRINTF("异常事件,文件句柄:%d,事件类型:%u(EPOLLIN:%u,EPOLLET:%u,EPOLHUP:%u,EPOLLERR:%u,EPOLLPRI:%u,EPOLLONESHOT:%u)-(ERROR->EBADF:%u,EFAULT:%u,EINVAL:%u,EINTR:%u)",
- event2s[i].data.fd,event2s[i].events,EPOLLIN,EPOLLET,
- EPOLLHUP,EPOLLERR,EPOLLPRI,EPOLLONESHOT,EBADF,EFAULT,EINVAL,EINTR);
- continue;
- }
- }
- }
-
- }
- void* ServerThread(void* vparam)
- {
- Recv();
-
- return NULL;
- }
- void* ClientThread(void* vparam)
- {
- Send();
-
- MYPRINTF("Over");
- return NULL;
- }
- int main(int argc,char* argv[])
- {
- int nCmd;//1,启动服务端; 非1,启动客户端
-
- if (argc > 1)
- {
- if (argc !=4)
- {
- MYPRINTF("参数不对->%d",argc);
- return -1;
- }
- nCmd = atoi(argv[1]);
- strcpy(g_szServerIP,argv[2]);
- g_sServerPort = atoi(argv[3]);
- }
- else
- {
- strcpy(g_szServerIP,"127.0.0.1");
- g_sServerPort = 10000;
- nCmd = 1;
- }
- MYPRINTF("CMD:%d\n",nCmd);
- MYPRINTF("IP:%s",g_szServerIP);
- MYPRINTF("PORT:%d\n",g_sServerPort);
-
-
- pthread_t tServerThread,tClientThread;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
-
- if (1 == nCmd )
- {
- if (pthread_create(&tServerThread,&attr,ServerThread,NULL))
- {
- MYPRINTF("Create thread failed!");
- return -1;
- }
- }
- else
- {
- if (pthread_create(&tClientThread,&attr,ClientThread,NULL))
- {
- MYPRINTF("Create thread failed!");
- return -1;
- }
- }
-
- pthread_attr_destroy(&attr);
-
- sleep(100);
- return 0;
- }
复制代码
[ 本帖最后由 leponylp 于 2007-10-11 22:58 编辑 ] |
|