说明:当客户端连接数超过64个的时候,每次最多select64个,但每一帧可以select多次,理论上可以突破fd个数的限制
.h
#ifndef _MODULE_SELECT_H_
#define _MODULE_SELECT_H_
#include "platform/platform.h" class CModuleSelect
{
public:
CModuleSelect();
~CModuleSelect();
public:
int32_t Initialize();
int32_t Uninitialize();
void ProcessEvent(uint32_t nTimeUsec);
public:
int32_t AddFd(int32_t fd);
int32_t DelFd(uint32_t index);
protected:
void FDSet(int32_t fd)
{
FD_SET(fd, &readfds); FD_SET(fd, &writefds); FD_SET(fd, &errorfds);
if (fd + > maxfdp){ maxfdp = fd + ; }
}
void FDZero()
{
FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&errorfds);
maxfdp = ;
}
void FDClear(int32_t fd)
{
FD_CLR(fd, &readfds); FD_CLR(fd, &writefds); FD_CLR(fd, &errorfds);
};
private:
int32_t sListen;
// fd_set for select
int32_t maxfdp;
struct fd_set readfds, writefds, errorfds;
// all used fd
uint32_t unFdSize;
int32_t *arrFd;
}; #endif
.cpp
#include "module_select.h"
#include "common/common.h" CModuleSelect::CModuleSelect()
{
unFdSize = ;
arrFd = new int32_t[unMaxFdSize];
} CModuleSelect::~CModuleSelect()
{
Uninitialize();
} int32_t CModuleSelect::Initialize()
{
WSADATA wsaData;
int32_t nRet = WSAStartup(0x0202, &wsaData);
if (nRet != S_OK){ return WSAGetLastError(); }
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
nRet = AddFd(sListen);
if (nRet != S_OK){ return nRet; } SOCKADDR_IN addrLocal;
addrLocal.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrLocal.sin_family = AF_INET;
addrLocal.sin_port = htons(nPort); // bind
nRet = bind(sListen, (struct sockaddr*)&addrLocal, sizeof(SOCKADDR_IN));
if (nRet != S_OK){ return WSAGetLastError(); } // listen
nRet = listen(sListen, );
if (nRet != S_OK){ return WSAGetLastError(); }
printf("listen:%d\n", sListen);
return S_OK;
} void CModuleSelect::ProcessEvent(uint32_t nTimeUsec)
{
int32_t nRet = S_OK;
static struct timeval timeout;
timeout.tv_sec = nTimeUsec / ;
timeout.tv_usec = nTimeUsec % ; static int32_t addrSize = sizeof(SOCKADDR_IN);
static char buf[];
static SOCKADDR_IN addrRemote;
// select all used fd
uint32_t unStartPos = , unEndPos = ;
do
{
// reset fd_set
FDZero();
// fd_set size limited by 'FD_SETSIZE'
for (uint32_t i = ; i < FD_SETSIZE && unEndPos < unFdSize; ++i)
{
FDSet(arrFd[unEndPos++]);
}
nRet = select(maxfdp, &readfds, &writefds, &errorfds, &timeout);
// select error
if (nRet == -)
{
int32_t nError = WSAGetLastError();
perrors("select error,nRet=%d,info=%s\n", nError, strerror(nError));
exit();
}
// time out ,nothing happened
else if (nRet == )
{
printf(".");
continue;
}
// some thing happened
else if (nRet > )
{
// check events
for (uint32_t i = unStartPos; i < unEndPos; ++i)
{
// read events
if ( FD_ISSET(arrFd[i],&readfds) )
{
printf("[%d]:read = %d\n",i,arrFd[i]);
if (sListen == arrFd[i])
{
nRet = accept(sListen, (struct sockaddr*)&addrRemote, &addrSize);
printf("Accepted client:%s:%d\n", inet_ntoa(addrRemote.sin_addr), ntohs(addrRemote.sin_port));
AddFd(nRet);
}
else
{
nRet = recv(arrFd[i], buf, , );
if (nRet == || nRet == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
{
// client close
DelFd(i);
}
else
{
// received correct data from client
buf[nRet] = '\0';
send(arrFd[i], buf, strlen(buf), );
}
}
}
// write events
else if (FD_ISSET(arrFd[i], &writefds))
{
Sleep();
//printf("write = %d\n", arrFd[i]);
}
// error events
else if (FD_ISSET(arrFd[i], &errorfds))
{
printf("error = %d\n", arrFd[i]);
}
}
}
// for next loop
unStartPos = unEndPos;
}while (unEndPos < unFdSize);
} int32_t CModuleSelect::Uninitialize()
{
return WSACleanup();
} int32_t CModuleSelect::AddFd(int32_t fd)
{
if (unFdSize < unMaxFdSize)
{
arrFd[unFdSize++] = fd;
return S_OK;
}
return -;
} int32_t CModuleSelect::DelFd(uint32_t index)
{
if (unFdSize > && index > && unFdSize > index)
{
closesocket(arrFd[index]);
arrFd[index] = arrFd[unFdSize - ];
--unFdSize;
}
return S_OK;
}