📄 sockgen.c
字号:
}#endif /* ! UEMF *//******************************************************************************//* * Define the events of interest */void socketRegisterInterest(socket_t *sp, int handlerMask){ a_assert(sp); sp->handlerMask = handlerMask;#ifndef UEMF if (handlerMask) { sp->fileHandle = emfCreateFileHandler(sp->sock, handlerMask, (emfFileProc *) socketEventProc, (void *) sp->sid); } else { emfDeleteFileHandler(sp->fileHandle); sp->fileHandle = -1; }#endif /* ! UEMF */}/******************************************************************************//* * Wait until an event occurs on a socket. Return 1 on success, 0 on failure. * or -1 on exception (UEMF only) */int socketWaitForEvent(socket_t *sp, int handlerMask, int *errCode){ int mask; a_assert(sp); mask = sp->handlerMask; sp->handlerMask |= handlerMask; while (socketSelect(sp->sid, 1000)) { if (sp->currentEvents & (handlerMask | SOCKET_EXCEPTION)) { break; } } sp->handlerMask = mask; if (sp->currentEvents & SOCKET_EXCEPTION) { return -1; } else if (sp->currentEvents & handlerMask) { return 1; } if (errCode) { *errCode = errno = EWOULDBLOCK; } return 0;}/******************************************************************************//* * Return TRUE if there is a socket with an event ready to process, */int socketReady(int sid){ socket_t *sp; int all; all = 0; if (sid < 0) { sid = 0; all = 1; } for (; sid < socketMax; sid++) { if ((sp = socketList[sid]) == NULL) { if (! all) { break; } else { continue; } } if (sp->flags & SOCKET_CONNRESET) { socketCloseConnection(sid); return 0; } if (sp->currentEvents & sp->handlerMask) { return 1; }/* * If there is input data, also call select to test for new events */ if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) { socketSelect(sid, 0); return 1; } if (! all) { break; } } return 0;}/******************************************************************************//* * Wait for a handle to become readable or writable and return a number of * noticed events. Timeout is in milliseconds. */#if (defined (WIN) || defined (CE) || defined (NW))int socketSelect(int sid, int timeout){ struct timeval tv; socket_t *sp; fd_set readFds, writeFds, exceptFds; int nEvents; int all, socketHighestFd; /* Highest socket fd opened */ FD_ZERO(&readFds); FD_ZERO(&writeFds); FD_ZERO(&exceptFds); socketHighestFd = -1; tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000;/* * Set the select event masks for events to watch */ all = nEvents = 0; if (sid < 0) { all++; sid = 0; } for (; sid < socketMax; sid++) { if ((sp = socketList[sid]) == NULL) { continue; } a_assert(sp);/* * Set the appropriate bit in the ready masks for the sp->sock. */ if (sp->handlerMask & SOCKET_READABLE) { FD_SET(sp->sock, &readFds); nEvents++; if (socketInputBuffered(sid) > 0) { tv.tv_sec = 0; tv.tv_usec = 0; } } if (sp->handlerMask & SOCKET_WRITABLE) { FD_SET(sp->sock, &writeFds); nEvents++; } if (sp->handlerMask & SOCKET_EXCEPTION) { FD_SET(sp->sock, &exceptFds); nEvents++; } if (! all) { break; } }/* * Windows select() fails if no descriptors are set, instead of just sleeping * like other, nice select() calls. So, if WIN, sleep. */ if (nEvents == 0) { Sleep(timeout); return 0; }/* * Wait for the event or a timeout. */ nEvents = select(socketHighestFd+1, &readFds, &writeFds, &exceptFds, &tv); if (all) { sid = 0; } for (; sid < socketMax; sid++) { if ((sp = socketList[sid]) == NULL) { continue; } if (FD_ISSET(sp->sock, &readFds) || socketInputBuffered(sid) > 0) { sp->currentEvents |= SOCKET_READABLE; } if (FD_ISSET(sp->sock, &writeFds)) { sp->currentEvents |= SOCKET_WRITABLE; } if (FD_ISSET(sp->sock, &exceptFds)) { sp->currentEvents |= SOCKET_EXCEPTION; } if (! all) { break; } } return nEvents;}#else /* not WIN || CE || NW */int socketSelect(int sid, int timeout){ socket_t *sp; struct timeval tv; fd_mask *readFds, *writeFds, *exceptFds; int all, len, nwords, index, bit, nEvents;/* * Allocate and zero the select masks */ nwords = (socketHighestFd + NFDBITS) / NFDBITS; len = nwords * sizeof(int); readFds = balloc(B_L, len); memset(readFds, 0, len); writeFds = balloc(B_L, len); memset(writeFds, 0, len); exceptFds = balloc(B_L, len); memset(exceptFds, 0, len); tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000;/* * Set the select event masks for events to watch */ all = nEvents = 0; if (sid < 0) { all++; sid = 0; } for (; sid < socketMax; sid++) { if ((sp = socketList[sid]) == NULL) { if (all == 0) { break; } else { continue; } } a_assert(sp);/* * Initialize the ready masks and compute the mask offsets. */ index = sp->sock / (NBBY * sizeof(fd_mask)); bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask))); /* * Set the appropriate bit in the ready masks for the sp->sock. */ if (sp->handlerMask & SOCKET_READABLE) { readFds[index] |= bit; nEvents++; if (socketInputBuffered(sid) > 0) { tv.tv_sec = 0; tv.tv_usec = 0; } } if (sp->handlerMask & SOCKET_WRITABLE) { writeFds[index] |= bit; nEvents++; } if (sp->handlerMask & SOCKET_EXCEPTION) { exceptFds[index] |= bit; nEvents++; } if (! all) { break; } }/* * Wait for the event or a timeout. Reset nEvents to be the number of actual * events now. */ nEvents = select(socketHighestFd + 1, (fd_set *) readFds, (fd_set *) writeFds, (fd_set *) exceptFds, &tv); if (nEvents > 0) { if (all) { sid = 0; } for (; sid < socketMax; sid++) { if ((sp = socketList[sid]) == NULL) { if (all == 0) { break; } else { continue; } } index = sp->sock / (NBBY * sizeof(fd_mask)); bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask))); if (readFds[index] & bit || socketInputBuffered(sid) > 0) { sp->currentEvents |= SOCKET_READABLE; } if (writeFds[index] & bit) { sp->currentEvents |= SOCKET_WRITABLE; } if (exceptFds[index] & bit) { sp->currentEvents |= SOCKET_EXCEPTION; } if (! all) { break; } } } bfree(B_L, readFds); bfree(B_L, writeFds); bfree(B_L, exceptFds); return nEvents;}#endif /* WIN || CE *//******************************************************************************//* * Process socket events */void socketProcess(int sid){ socket_t *sp; int all; all = 0; if (sid < 0) { all = 1; sid = 0; }/* * Process each socket */ for (; sid < socketMax; sid++) { if ((sp = socketList[sid]) == NULL) { if (! all) { break; } else { continue; } } if (socketReady(sid)) { socketDoEvent(sp); } if (! all) { break; } }}/******************************************************************************//* * Process an event on the event queue */static int socketDoEvent(socket_t *sp){ ringq_t *rq; int sid; a_assert(sp); sid = sp->sid; if (sp->currentEvents & SOCKET_READABLE) { if (sp->flags & SOCKET_LISTENING) { socketAccept(sp); sp->currentEvents = 0; return 1; } } else {/* * If there is still read data in the buffers, trigger the read handler * NOTE: this may busy spin if the read handler doesn't read the data */ if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) { sp->currentEvents |= SOCKET_READABLE; } }/* * If now writable and flushing in the background, continue flushing */ if (sp->currentEvents & SOCKET_WRITABLE) { if (sp->flags & SOCKET_FLUSHING) { rq = &sp->outBuf; if (ringqLen(rq) > 0) { socketFlush(sp->sid); } else { sp->flags &= ~SOCKET_FLUSHING; } } }/* * Now invoke the users socket handler. NOTE: the handler may delete the * socket, so we must be very careful after calling the handler. */ if (sp->handler && (sp->handlerMask & sp->currentEvents)) { (sp->handler)(sid, sp->handlerMask & sp->currentEvents, sp->handler_data);/* * Make sure socket pointer is still valid, then reset the currentEvents. */ if (socketList && sid < socketMax && socketList[sid] == sp) { sp->currentEvents = 0; } } return 1;}/******************************************************************************//* * Set the socket blocking mode */int socketSetBlock(int sid, int on){ socket_t *sp; unsigned long flag; int iflag; int oldBlock; flag = iflag = !on; if ((sp = socketPtr(sid)) == NULL) { a_assert(0); return 0; } oldBlock = (sp->flags & SOCKET_BLOCK); sp->flags &= ~(SOCKET_BLOCK); if (on) { sp->flags |= SOCKET_BLOCK; }/* * Put the socket into block / non-blocking mode */ if (sp->flags & SOCKET_BLOCK) {#if (defined (CE) || defined (WIN)) ioctlsocket(sp->sock, FIONBIO, &flag);#elif (defined (ECOS)) int off; off = 0; ioctl(sp->sock, FIONBIO, &off);#elif (defined (VXWORKS) || defined (NW)) ioctl(sp->sock, FIONBIO, (int)&iflag);#else fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) & ~O_NONBLOCK);#endif } else {#if (defined (CE) || defined (WIN)) ioctlsocket(sp->sock, FIONBIO, &flag);#elif (defined (ECOS)) int on; on = 1; ioctl(sp->sock, FIONBIO, &on);#elif (defined (VXWORKS) || defined (NW)) ioctl(sp->sock, FIONBIO, (int)&iflag);#else fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) | O_NONBLOCK);#endif } return oldBlock;}/******************************************************************************//* * Return true if a readable socket has buffered data. - not public */int socketDontBlock(){ socket_t *sp; int i; for (i = 0; i < socketMax; i++) { if ((sp = socketList[i]) == NULL || (sp->handlerMask & SOCKET_READABLE) == 0) { continue; } if (socketInputBuffered(i) > 0) { return 1; } } return 0;}/******************************************************************************//* * Return true if a particular socket buffered data. - not public */int socketSockBuffered(int sock){ socket_t *sp; int i; for (i = 0; i < socketMax; i++) { if ((sp = socketList[i]) == NULL || sp->sock != sock) { continue; } return socketInputBuffered(i); } return 0;}#endif /* (!WIN) | LITTLEFOOT | WEBS *//******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -