void readDataFromClient(epoller *epoll, int fd, void *privdata, int mask) { echoClientContext *client = (echoClientContext *)privdata; NOTUSED(client); char buf[IOBUF_LEN]; int nread; NOTUSED(epoll); NOTUSED(mask); nread = read(fd, buf, IOBUF_LEN); int destroy = 0; if(nread > 0) { kbuffer_add_data(client->writebuffer, buf, nread); if(epollAddEvent(epoll, fd, EPOLLOUT, writeDataToClient, client) != 0) destroy = 1; } else if(nread == 0) { destroy = 1; } else if(nread < 0) { if(errno == EAGAIN) { nread = 0; } else { destroy = 1; } } if(destroy) { close(fd); epollDelEvent(epoll, fd, EPOLLIN | EPOLLOUT); } }
//-------------------------------------------------------------------------------- // SERVER void acceptTcpHandler(epoller *epoll, int fd, void *privdata, int mask) { int cport, cfd = -1; char cip[128] = {0, }; echoServerContext *server = (echoServerContext *)privdata; NOTUSED(server); NOTUSED(epoll); NOTUSED(mask); struct sockaddr_in sa; socklen_t salen = sizeof(sa); while(1) { cfd = accept(fd, (struct sockaddr *)&sa, &salen); if (cfd == -1) { if (errno == EINTR) continue; else { oom("accept error : %s", strerror(errno)); return; } } break; } if (cfd == -1) { printf("failed to accepting client connection\n"); return; } strcpy(cip, inet_ntoa(sa.sin_addr)); cport = ntohs(sa.sin_port); printf("Accepted %s:%d\n", cip, cport); // client object create.. echoClientContext *c = (echoClientContext *)malloc(sizeof(echoClientContext)); c->writebuffer = kbuffer_new(); if (epollAddEvent(epoll, cfd, EPOLLIN, readDataFromClient, c) != 0) oom("failed to add client event.."); }
//可重入函数:处理连接请求 int epollHandleAccept(int _epollFd,int _listenFd) { int clientFd; struct sockaddr_in clientAddr; int c=sizeof(struct sockaddr_in); clientFd=accept(_listenFd,(struct sockaddr *)&clientAddr,(socklen_t *)&c); if(clientFd==-1){ printf("epoll handle accept failed! epollFd: %d listenFd: %d errno: %d\n",_epollFd,_listenFd,errno); return -1; } else{ char str[INET_ADDRSTRLEN]; inet_ntop(AF_INET,&(clientAddr.sin_addr),str,INET_ADDRSTRLEN); printf("epoll %d-listenFd %d accept new connect: fd %d %s:%d\n",_epollFd,_listenFd,clientFd,str,clientAddr.sin_port); //设置新接入的socket为非阻塞 makeSocketNonBlocking(clientFd); //为新接入的socket注册事件 epollAddEvent(_epollFd,clientFd,EPOLLIN|EPOLLET); return clientFd; } }
int main(int argc, char **argv) { if(argc < 2) { printf("usage : %s <port>\n", argv[0]); exit(1); } int port = atoi(argv[1]); epoller *ep = epollCreate(); echoServerContext *server = createTcpServer(ep, port); if(epollAddEvent(ep, server->serverfd, EPOLLIN, acceptTcpHandler, NULL) != 0) oom("creating file event"); epollDispatch(ep); epollDelete(ep); printf("Bye!\n"); return 0; }
int listenClients(int _localServerFd) { int clientListenFd=createSocketAndBind(CLIENT_LISTEN_PORT); //设置套接字为非阻塞 int errorCode=0; if((errorCode=makeSocketNonBlocking(clientListenFd))<0){ printf("create client listen scoket failed! errno: %d\n",errno); return -1; } //监听套接字,SOMAXCONN为系统默认的最大连接个数 if((errorCode=listen(clientListenFd,SOMAXCONN))<0){ printf("create client listen scoket failed! errno: %d\n",errno); return -2; } //以下为使用IO多路复用模型函数epool来监控接入 struct epoll_event events[EPOLL_EVENTS_SIZE]; int epollFd; if((epollFd=epoll_create(EPOLL_FD_SIZE))<0){ printf("create epoll failed! errno: %d\n",errno); return -3; } //添加监听描述符事件 epollAddEvent(epollFd,clientListenFd,EPOLLIN|EPOLLET); epollAddEvent(epollFd,_localServerFd,EPOLLIN|EPOLLET); char buffer[SENSORS_DATA_MAX_SIZE]; memset(buffer,'0',SENSORS_DATA_MAX_SIZE); //this is used for record valid client fd std::map<int,int> connectedClientMap; //循环等待 while(1){ int eventsNum=epoll_wait(epollFd,events,EPOLL_EVENTS_SIZE,-1); for(int i=0;i<eventsNum;++i){ //根据事件描述符类型和事件类型进行处理 int fdTmp=events[i].data.fd; uint32_t eventsTmp=events[i].events; // printf("localServerFd:%d clientListenFd:%d fdTmp:%d events: %d EPOLLERR:%d EPOLLHUP:%d EPOLLRDHUP:%d EPOLLIN:%d EPOLLOUT:%d\n",_localServerFd,clientListenFd,fdTmp,eventsTmp,EPOLLERR,EPOLLHUP,EPOLLRDHUP,EPOLLIN,EPOLLOUT); //处理错误和挂起 if((eventsTmp&EPOLLERR)||(eventsTmp&EPOLLHUP)||(eventsTmp&EPOLLRDHUP)){ printf("epoll error occured!\n"); epollHandleError(epollFd,fdTmp,eventsTmp); } //处理有新连接接入 else if((fdTmp==clientListenFd)&&(eventsTmp&EPOLLIN)){ int connectedClient=epollHandleAccept(epollFd,clientListenFd); if(connectedClient>0){ connectedClientMap.insert(std::pair<int,int>(connectedClient,connectedClient)); } } //this is used for read local client in background process 's data else if((fdTmp==_localServerFd)&&(eventsTmp&EPOLLIN)){ memset(buffer,'\0',SENSORS_DATA_MAX_SIZE); int nRecv=recv(_localServerFd,buffer,SENSORS_DATA_MAX_SIZE,0); if(nRecv==SENSORS_DATA_FRAME_SIZE){ for(int i=0;i<SENSORS_DATA_FRAME_SIZE;++i){ // printf("|%c",buffer[i]); } printf("valid client fd: "); for(std::map<int,int>::iterator it=connectedClientMap.begin();it!=connectedClientMap.end();++it){ printf("%d ",it->second); send(it->second,buffer,SENSORS_DATA_FRAME_SIZE,0); } printf("\n"); } else{ printf("local client received %d bytes errno: %d\n",nRecv,errno); } } //this is used for handle other client's data else if(eventsTmp&EPOLLIN){ if(epollHandleRead(epollFd,fdTmp,buffer,SENSORS_DATA_MAX_SIZE)<0){ //read error occured! remove fd from valid connected map connectedClientMap.erase(fdTmp); } } else if(eventsTmp&EPOLLOUT){ // epollHandleWrite(epollFd,fdTmp,buffer,SENSORS_DATA_MAX_SIZE); } } } free(events); close(clientListenFd); return 0; }
int listenSensors(int _localClientFd) { //建立监听传感器设备的套接字 int sensorsListenFd=createSocketAndBind(DEVICE_LISTEN_PORT); //设置套接字为非阻塞 int errorCode=0; if((errorCode=makeSocketNonBlocking(sensorsListenFd))<0){ printf("create sensors listen scoket failed! errno: %d\n",errno); return -1; } //监听套接字,SOMAXCONN为系统默认的最大连接个数 if((errorCode=listen(sensorsListenFd,SOMAXCONN))<0){ printf("create sensors listen scoket failed! errno: %d\n",errno); return -2; } //以下为使用IO多路复用模型函数epool来监控设备的接入 struct epoll_event events[EPOLL_EVENTS_SIZE]; int epollFd; if((epollFd=epoll_create(EPOLL_FD_SIZE))<0){ printf("create epoll failed! errno: %d\n",errno); return -3; } //添加监听描述符事件 epollAddEvent(epollFd,sensorsListenFd,EPOLLIN|EPOLLET); char buffer[SENSORS_DATA_MAX_SIZE]; memset(buffer,'A',SENSORS_DATA_MAX_SIZE); std::map<int,int> connectedSensorMap; //循环等待 while(1){ int eventsNum=epoll_wait(epollFd,events,EPOLL_EVENTS_SIZE,-1); for(int i=0;i<eventsNum;++i){ //根据事件描述符类型和事件类型进行处理 int fdTmp=events[i].data.fd; //处理错误和挂起 if(events[i].events&(EPOLLERR|EPOLLHUP|EPOLLRDHUP)){ epollHandleError(epollFd,fdTmp,events[i].events); } //处理有新连接接入 else if((fdTmp==sensorsListenFd)&&(events[i].events&EPOLLIN)){ int connectedSensor=epollHandleAccept(epollFd,sensorsListenFd); if(connectedSensor>0){ connectedSensorMap.insert(std::pair<int,int>(connectedSensor,connectedSensor)); } } else if(events[i].events&EPOLLIN){ int nRecv=epollHandleRead(epollFd,fdTmp,buffer,SENSORS_DATA_MAX_SIZE); if(nRecv==SENSORS_DATA_FRAME_SIZE){ send(_localClientFd,buffer,SENSORS_DATA_FRAME_SIZE,0); } else if(nRecv<0){ connectedSensorMap.erase(fdTmp); } printf("valid sensor fd: "); for(std::map<int,int>::iterator it=connectedSensorMap.begin();it!=connectedSensorMap.end();++it){ printf("%d ",it->second); } printf("\n"); } else if(events[i].events&EPOLLOUT){ // epollHandleWrite(epollFd,fdTmp,buffer,SENSORS_DATA_MAX_SIZE); } } } free(events); close(sensorsListenFd); return 0; }