问一个I/O异步 select模型的问题
最近学习I/O异步 select模型,看到一些源代码有点疑惑。
为什么每次都需要将fdset集合里面的socket清空,
看到几个源代码就是这样的
不是可以判断它下线了吗?知道它下线,就可以用FD_CLR宏定义来消去里面的socket吗?
下面是上度娘找的一个源代码
- C/C++ code
#include <WinSock.h> #pragma comment(lib, "ws2_32.lib") #define MAXSOCKETCON 200 SOCKET ClientSockets[MAXSOCKETCON]; int NowClientSocket = 0; SOCKET socketServer; int CreateServerSocket(int Port) { int iErrCode; WSADATA wsaData; iErrCode = WSAStartup(0x0202, &wsaData); int iRes; //创建Socket socketServer = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); //绑定 SOCKADDR_IN addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //addr.sin_addr.s_addr = 0x010000ff; addr.sin_port = htons(Port); iRes = bind(socketServer,(LPSOCKADDR)&addr,sizeof(addr)); if(iRes == SOCKET_ERROR) { closesocket(socketServer); return -1; } iRes = listen(socketServer, MAXSOCKETCON); if(iRes == SOCKET_ERROR) { closesocket(socketServer); return -1; } return 1; } DWORD WINAPI RecvProc(LPVOID pParam) { char Data[256]; int iBuffer = 0; TIMEVAL TimeOut = {1, 0}; while (1) { if(NowClientSocket == 0) { continue; } fd_set ReadSet; FD_ZERO(&ReadSet); for (int i = 0; i<NowClientSocket;i++) { FD_SET(ClientSockets[i], &ReadSet); } select(0, &ReadSet, NULL, NULL, &TimeOut); for (int i=0; i<NowClientSocket;i++) { if(FD_ISSET(ClientSockets[i], &ReadSet)) { iBuffer = recv(ClientSockets[i], Data, 256, 0); if(iBuffer>0) { printf("(%d)%s", i , Data); } } } } } DWORD WINAPI AcceptProc(LPVOID pParam) { SOCKADDR_IN addr; int addrLen = sizeof(addr); SOCKET tempSocket; while (1) { tempSocket = accept(socketServer, (sockaddr*)&addr, &addrLen); if (tempSocket == INVALID_SOCKET) { return 0; } ClientSockets[NowClientSocket] = tempSocket; NowClientSocket++; } } int _tmain(int argc, _TCHAR* argv[]) { if(CreateServerSocket(6565)<1) return 0; CreateThread(NULL, NULL, &AcceptProc, NULL, NULL, NULL); CreateThread(NULL, NULL, &RecvProc, NULL, NULL, NULL); while(1) { Sleep(1000); } return 0; } [解决办法]
int select(int nfds, fd_set *restrict readfds,
fd_set *restrict writefds, fd_set *restrict errorfds,
struct timeval *restrict timeout);
Upon successful completion, the pselect() or select() function shall modify the objects pointed to by the readfds, writefds, and errorfds arguments to indi-
cate which file descriptors are ready for reading, ready for writing, or have an error condition pending, respectively, and shall return the total number of
ready descriptors in all the output sets. For each file descriptor less than nfds, the corresponding bit shall be set on successful completion if it was set
on input and the associated condition is true for that file descriptor.
如果你意识到你之前的代码都是完全错误的, 你就知道为什么他们要那么做了。
一般需要维护两套set,一套是在线用户的,一套是传给select让它去改的。
[解决办法]