📄 select.c
字号:
/*---------------------------------------------------------------*/ /* Only check TCP sockets (UDP sockets can't have urgent data). */ /*---------------------------------------------------------------*/ if (sock->type == SOCK_STREAM) { /*-------------------------------------------------------------*/ /* Set all event bits we would wait for. */ /*-------------------------------------------------------------*/ sock->sel_evnts |= SE_CLOSED | SE_GOT_FIN | SE_URGENT | SE_RCV_SHUT; /*-------------------------------------------------------------*/ /* Socket has received urgent data if flag is set. */ /*-------------------------------------------------------------*/ if (sock->flags & SF_RUPOK) exceptf = TRUE; } /*---------------------------------------------------------------*/ /* If testing and OOB test passed, return TRUE. Else if final */ /* loop and test failed, excluded socket from output list. */ /*---------------------------------------------------------------*/ if (mode == TESTING) { if (exceptf) return TRUE; } else /* mode == RETURNING */ { if (!exceptf) FD_CLR(s, excepts); } } /*-----------------------------------------------------------------*/ /* Increment count if this socket satisfied either test. */ /*-----------------------------------------------------------------*/ if (readf || writef || exceptf) ++n; } return n;}/***********************************************************************//* Global Function Definitions *//***********************************************************************//***********************************************************************//* select: Check conditions on multiple sockets *//* *//* Inputs: numsock = number of sockets to check *//* reads = socket set to check for nonblocking read *//* writes = socket set to check for nonblocking write *//* excepts = socket set to check for urgent data *//* timeo = max wait if no sockets currently ready *//* *//* Returns: -1 if error. Otherwise the number of sockets meeting *//* the nonblocking access condition. *//* *//***********************************************************************/int select(int numsock, fd_set *reads, fd_set *writes, fd_set *excepts, const struct timeval *timeo){ int s, n; fd_set reserved; ui32 tick_timeo;#if OS_PARM_CHECK /*-------------------------------------------------------------------*/ /* Verify protocol has been initialized. */ /*-------------------------------------------------------------------*/ if (!Net.Initialized) { NetError(NULL, ENETDOWN); return -1; }#endif /*-------------------------------------------------------------------*/ /* Calculate blocking timeout. */ /*-------------------------------------------------------------------*/ if (timeo == NULL) tick_timeo = WAIT_FOREVER; else tick_timeo = Secs2Ticks(timeo->tv_sec) + Us2Ticks(timeo->tv_usec); /*-------------------------------------------------------------------*/ /* Initialize set of reserved sockets to zero. */ /*-------------------------------------------------------------------*/ FD_ZERO(&reserved); /*-------------------------------------------------------------------*/ /* Gain exclusive access to TCP/IP internals. */ /*-------------------------------------------------------------------*/ semPend(Net.IntSem, WAIT_FOREVER); /*-------------------------------------------------------------------*/ /* Find every socket in the combination of the three sets. */ /*-------------------------------------------------------------------*/ for (s = 1; s <= numsock; ++s) { if (((reads && FD_ISSET(s, reads)) || (writes && FD_ISSET(s, writes)) || (excepts && FD_ISSET(s, excepts)))) { SOCKET sock = &Socks[s - 1]; /*---------------------------------------------------------------*/ /* Error if socket is not open. */ /*---------------------------------------------------------------*/ if (InvalidHandle(s)) { n = -1; NetError(NULL, ENOTSOCK); goto sel_err; } /*---------------------------------------------------------------*/ /* Error if select() already in-progress on socket. */ /*---------------------------------------------------------------*/ else if (sock->sel_id) { n = -1; NetError(sock, ECOLL); goto sel_err; } /*---------------------------------------------------------------*/ /* Otherwise reserve socket, set task id, and remember socket. */ /*---------------------------------------------------------------*/ else { ++sock->reserve_cnt; sock->sel_id = RunningTask; sock->sel_evnts = 0; FD_SET(s, &reserved); } } } /*-------------------------------------------------------------------*/ /* Count number of tests met and exit if error occurred. */ /*-------------------------------------------------------------------*/ n = sock_loop(numsock, TESTING, reads, writes, excepts); if (n < 0) goto sel_err; /*-------------------------------------------------------------------*/ /* If no test met and wait OK, wait until notification that one has. */ /*-------------------------------------------------------------------*/ if ((n == 0) && tick_timeo) { taskLock(); semPost(Net.IntSem); taskSleep(tick_timeo); semPend(Net.IntSem, WAIT_FOREVER); } /*-------------------------------------------------------------------*/ /* Do final loop, counting successes and excluding misses. */ /*-------------------------------------------------------------------*/ n = sock_loop(numsock, RETURNING, reads, writes, excepts); /*-------------------------------------------------------------------*/ /* Release hold on all reserved sockets and clear our id. */ /*-------------------------------------------------------------------*/sel_err: for (s = 1; s <= numsock; ++s) { if (FD_ISSET(s, &reserved)) { SOCKET sock = &Socks[s - 1]; sock->sel_id = NULL; SockRelease(sock); } } /*-------------------------------------------------------------------*/ /* Release TCP/IP internals exclusive access and return ready count. */ /*-------------------------------------------------------------------*/ semPost(Net.IntSem); return n;}/***********************************************************************//* FD_ZERO: Initialize socket descriptor set to zero *//* *//* Input: fdset = pointer to socket descriptor set to zero *//* *//***********************************************************************/void FD_ZERO(fd_set *fdset){ int i; for (i = 0; i < MAX_NUM_SOCKETS; ++i) fdset->id[i] = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -