//--------------------------------------------------------------------- // 从捕捉的事件列表中查找下一个事件 //--------------------------------------------------------------------- static int apu_poll_event(apolld ipd, int *fd, int *event, void **user) { PSTRUCT *ps = PDESC(ipd); int revents, eventx = 0, n; struct pollfd *pfd; if (ps->results <= 0) return -1; if (ps->cur_res >= ps->results) return -2; pfd = &ps->mresult[ps->cur_res++]; revents = pfd->revents; if (revents & POLLIN) eventx |= APOLL_IN; if (revents & POLLOUT)eventx |= APOLL_OUT; if (revents & POLLERR)eventx |= APOLL_ERR; n = pfd->fd; if (ps->fv.fds[n].fd < 0) { eventx = 0; apu_changes_push(ipd, n, POLLREMOVE); } else { eventx &= ps->fv.fds[n].mask; if (eventx == 0) { apu_poll_set(ipd, n, ps->fv.fds[n].mask); } } if (fd) *fd = n; if (event) *event = eventx; if (user) *user = ps->fv.fds[n].user; return 0; }
//--------------------------------------------------------------------- // 设置 devpoll对象中某文件描述的事件 //--------------------------------------------------------------------- static int apu_poll_set(apolld ipd, int fd, int mask) { PSTRUCT *ps = PDESC(ipd); int events = 0; int retval; int save; if (fd >= ps->usr_len) return -1; if (ps->fv.fds[fd].fd < 0) return -2; save = ps->fv.fds[fd].mask; mask = mask & (APOLL_IN | APOLL_OUT | APOLL_ERR); if ((save & mask) != save) apu_changes_push(ipd, fd, POLLREMOVE); ps->fv.fds[fd].mask = mask; if (mask & APOLL_IN) events |= POLLIN; if (mask & APOLL_OUT) events |= POLLOUT; if (mask & APOLL_ERR) events |= POLLERR; retval = apu_changes_push(ipd, fd, events); return retval; }
//--------------------------------------------------------------------- // 调用 devpoll等待函数,捕捉事件 //--------------------------------------------------------------------- static int apu_poll_wait(apolld ipd, int timeval) { PSTRUCT *ps = PDESC(ipd); struct dvpoll dvp; int retval; if (ps->num_chg) { apu_changes_apply(ipd); } dvp.dp_fds = ps->mresult; dvp.dp_nfds = ps->max_fd * 2; dvp.dp_timeout = timeval; if (dvp.dp_nfds > ps->limit) { dvp.dp_nfds = ps->limit; } retval = ioctl(ps->dpfd, DP_POLL, &dvp); if (retval < 0) { if (errno != EINTR) { return -1; } return 0; } ps->results = retval; ps->cur_res = 0; return ps->results; }
//--------------------------------------------------------------------- // 提交 devpoll变更事件 //--------------------------------------------------------------------- static int apu_changes_apply(apolld ipd) { PSTRUCT *ps = PDESC(ipd); int num = ps->num_chg; if (num == 0) return 0; if (pwrite(ps->dpfd, ps->mchange, sizeof(struct pollfd) * num, 0) < 0) return -1; ps->num_chg = 0; return 0; }
//--------------------------------------------------------------------- // 销毁 devpoll描述符 //--------------------------------------------------------------------- static int apu_destroy_pd(apolld ipd) { PSTRUCT *ps = PDESC(ipd); iv_destroy(&ps->vresult); iv_destroy(&ps->vchange); apr_poll_fvdestroy(&ps->fv); if (ps->dpfd >= 0) close(ps->dpfd); ps->dpfd = -1; return 0; }
//--------------------------------------------------------------------- // 初始化 devpoll描述符 //--------------------------------------------------------------------- static int apu_init_pd(apolld ipd, int param) { PSTRUCT *ps = PDESC(ipd); int flags = O_RDWR; struct rlimit rl; #ifdef O_CLOEXEC flags |= O_CLOEXEC; #endif ps->dpfd = open("/dev/poll", flags); if (ps->dpfd < 0) return -1; #if (!defined(O_CLOEXEC)) && defined(FD_CLOEXEC) if (fcntl(ps->dpfd, F_SETFD, FD_CLOEXEC) < 0) { close(ps->dpfd); ps->dpfd = -1; return -2; } #endif iv_init(&ps->vresult, NULL); iv_init(&ps->vchange, NULL); apr_poll_fvinit(&ps->fv, NULL); ps->max_fd = 0; ps->num_fd = 0; ps->max_chg = 0; ps->num_chg = 0; ps->usr_len = 0; ps->limit = 32000; if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { if (rl.rlim_cur != RLIM_INFINITY) { if (rl.rlim_cur < 32000) { ps->limit = rl.rlim_cur; } } } if (apu_grow(ps, 4, 4)) { apu_destroy_pd(ipd); return -3; } param = param + 1; return 0; }
//--------------------------------------------------------------------- // 给 devpoll对象增加一个文件描述 //--------------------------------------------------------------------- static int apu_poll_add(apolld ipd, int fd, int mask, void *user) { PSTRUCT *ps = PDESC(ipd); int usr_nlen, i, events; if (ps->num_fd >= ps->max_fd) { if (apu_grow(ps, ps->max_fd * 2, -1)) return -1; } if (fd >= ps->usr_len) { usr_nlen = fd + 128; apr_poll_fvresize(&ps->fv, usr_nlen); for (i = ps->usr_len; i < usr_nlen; i++) { ps->fv.fds[i].fd = -1; ps->fv.fds[i].user = NULL; ps->fv.fds[i].mask = 0; } ps->usr_len = usr_nlen; } if (ps->fv.fds[fd].fd >= 0) { ps->fv.fds[fd].user = user; apu_poll_set(ipd, fd, mask); return 0; } events = 0; mask = mask & (APOLL_IN | APOLL_OUT | APOLL_ERR); if (mask & APOLL_IN) events |= POLLIN; if (mask & APOLL_OUT) events |= POLLOUT; if (mask & APOLL_ERR) events |= POLLERR; ps->fv.fds[fd].fd = fd; ps->fv.fds[fd].user = user; ps->fv.fds[fd].mask = mask & (APOLL_IN | APOLL_OUT | APOLL_ERR); if (apu_changes_push(ipd, fd, events) < 0) { return -2; } ps->num_fd++; return 0; }
//--------------------------------------------------------------------- // 在 devpoll对象中删除一个文件描述 //--------------------------------------------------------------------- static int apu_poll_del(apolld ipd, int fd) { PSTRUCT *ps = PDESC(ipd); if (ps->num_fd <= 0) return -1; if (ps->fv.fds[fd].fd < 0) return -2; apu_changes_push(ipd, fd, POLLREMOVE); ps->num_fd--; ps->fv.fds[fd].fd = -1; ps->fv.fds[fd].user = NULL; ps->fv.fds[fd].mask = 0; apu_changes_apply(ipd); return 0; }
//--------------------------------------------------------------------- // 增加一个 devpoll变更事件 //--------------------------------------------------------------------- static int apu_changes_push(apolld ipd, int fd, int events) { PSTRUCT *ps = PDESC(ipd); struct pollfd *pfd; if (fd >= ps->usr_len) return -1; if (ps->fv.fds[fd].fd < 0) return -2; if (ps->num_chg >= ps->max_chg) { if (apu_grow(ps, -1, ps->max_chg * 2)) return -3; } if (ps->num_chg + 1 >= ps->limit) { if (apu_changes_apply(ipd) < 0) return -4; } pfd = &ps->mchange[ps->num_chg++]; memset(pfd, 0, sizeof(struct pollfd)); pfd->fd = fd; pfd->events = events; pfd->revents = 0; return 0; }
/**< 数据处理流程(属于每个线程) */ void* ClientYinLian::YinLianPro(void* pPara) { trace_log(DBG,"start ClientYinLian::YinLianPro()"); struct pollfd fds[1]; unsigned char ucRecvbuff[nSglRead*16]={0}; unsigned char ucRecvTmp[nSglRead]={0}; int nRecvTmpLen=0; int nRead=0,nWrite=0;/**< 读数据、写数据的位置 */ int nFill=0; if(!pPara) { return NULL; } PDESC pDesc=PDESC(pPara); if(!pDesc->pCli) { return NULL; } ClientYinLian* pCli=(ClientYinLian*)pDesc->pCli; trace_log(DBG,"ClientYinLian::YinLianPro() in while(1),pCli:%p",pCli); try { while(1) { /**< 连接银联 */ if(!pDesc->bConn || 0 == pDesc->socket_desc) { nRead = 0; nWrite = 0; if(!pCli->Connect(pDesc)) { continue; } trace_log(DBG,"the cIp[%s] nPort[%d] connect ok",pDesc->cIp,pDesc->nPort); } fds[0].fd=pDesc->socket_desc; fds[0].events = POLLIN|POLLERR|POLLNVAL; while (1) { /**< 超时断开 */ time_t curTime = time(0); if(difftime(curTime,pDesc->tIdle) >= 30) { //发个心跳包 unsigned char data[2]={0,0}; PSNDDATA pSndData=new SNDDATA(); memset(pSndData,0,sizeof(SNDDATA)); memcpy(pSndData->sndBuff,data,2); pSndData->sndLen=2; pSndData->tTime=time(0); pSndData->isHeartBeat=1; pCli->LockListSnd(); pCli->listSnd.push_back(pSndData); pCli->UnLockListSnd(); } else if(difftime(curTime,pDesc->tIdle) >= nIdleTime) { pDesc->bConn=false; if(pDesc->socket_desc) { close(pDesc->socket_desc); } pDesc->socket_desc=0; pCli->nConn--; trace_log(ERR,"pDesc->tIdle>nIdleTime[%d]",nIdleTime); break; } /**< 发送数据 */ int ret = pCli->SndData(pDesc); if(ret == 0) { trace_log(ERR,"pCli->SndData ERR"); break; } else if(ret == 2) { //trace_log(DBG,"Send Success HeadtBeat,No Read..."); continue; } /**< 错误处理 */ int retval = poll(fds, 1, 5); if (retval < 0) { pDesc->bConn=false; if(pDesc->socket_desc) { close(pDesc->socket_desc); } pDesc->socket_desc=0; pCli->nConn--; trace_log(ERR,"retval = poll()<0"); break; } if (fds[0].revents & POLLERR||fds[0].revents & POLLNVAL) { pDesc->bConn=false; if(pDesc->socket_desc) { close(pDesc->socket_desc); } pDesc->socket_desc=0; pCli->nConn--; trace_log(ERR,"retval = poll():POLLERR||POLLNVAL"); break; } /**< 读数据 */ if (fds[0].revents & POLLIN) { trace_log(DBG,"retval = poll():POLLIN,nRead:%d,nWrite:%d,retval:%d",nRead,nWrite,retval); pDesc->tIdle=time(0); nFill = (nRead > nWrite) ? ( nRead - nWrite):(nSglRead*16 + nWrite - nRead); if(nFill > nSglRead) { trace_log(DBG," START RecvData(pDesc,ucRecvTmp,nRecvTmpLen)"); nRecvTmpLen=sizeof(ucRecvTmp); if(pCli->RecvData(pDesc,ucRecvTmp,nRecvTmpLen)) { int nRight=nSglRead * 16 - nWrite; if(nRight > nRecvTmpLen) { memcpy(ucRecvbuff+nWrite,ucRecvTmp,nRecvTmpLen); nWrite += nRecvTmpLen; } else { memcpy(ucRecvbuff+nWrite,ucRecvTmp,nRight); nWrite = nRecvTmpLen-nRight; memcpy(ucRecvbuff,ucRecvTmp+nRight,nWrite); } trace_log(DBG,"RecvData(pDesc,ucRecvTmp,nRecvTmpLen:%d) OK,nRead:%d,nWrite:%d", nRecvTmpLen,nRead,nWrite); } else { trace_log(DBG,"RecvData(pDesc,ucRecvTmp,nRecvTmpLen) fail"); break; } } } /**< 解包 */ pCli->UpPack(ucRecvbuff,nWrite,nRead); } } return NULL; }catch(...){ trace_log(ERR,"Error in ClientYinLian::YinLianPro()"); } return NULL; }