Select模型头文件
#ifndef __SELECT_H__
#define __SELECT_H__
#define ERROR_SELECT_MAXFD 1
#define ERROR_SELECT_INVALID 2
#define ERROR_SELECT_SOCKET 3
namespace LinWin
{
class CNetworkEvent;
class CError;
class CExit;
class CSelectImpl
{
private:
net_socket_fd m_fdListen;
fd_set m_fdSocket;
public:
explicit CSelectImpl(net_socket_fd fdListen);
void SetListenFd(net_socket_fd fdListen);
int Select(CNetworkEvent* pEvent, CError* pError, CExit* pExit);
};
}
#endif
实现文件
#include "Platform.h"
#include "Select.h"
#include "NetworkEvent.h"
#include "Error.h"
#include "Exit.h"
#define MAX_CLIENT_NUM 16
LinWin::CSelectImpl::CSelectImpl(net_socket_fd fdListen) : m_fdListen(fdListen)
{
}
void LinWin::CSelectImpl::SetListenFd(net_socket_fd fdListen)
{
if (m_fdListen == NET_INVALID_SOCKET)
m_fdListen = fdListen;
}
int LinWin::CSelectImpl::Select(CNetworkEvent* pEvent, CError* pError, CExit* pExit)
{
int ret;
int i, j;
int nClientCount = 1;
fd_set fdReads;
if (m_fdListen == NET_INVALID_SOCKET)
return ERROR_SELECT_SOCKET;
FD_ZERO(&m_fdSocket);
FD_SET(m_fdListen, &m_fdSocket);
if (!pEvent || !pError || !pExit)
return ERROR_SELECT_INVALID;
net_socket_fd client_fd[MAX_CLIENT_NUM];
client_fd[0] = m_fdListen;
for (int i = 1; i < MAX_CLIENT_NUM; i++)
client_fd[i] = -1;
#ifndef WINDOWS_FAMILY
int maxfd;
#endif
while (1)
{
ret = 0;
if (pExit->OnExit())
break;
fdReads = m_fdSocket;
#ifdef WINDOWS_FAMILY
ret = ::select(0, &fdReads, NULL, NULL, NULL);
#else
maxfd = m_fdListen;
for(i = 0; i < MAX_CLIENT_NUM; i++)
{
if (maxfd < client_fd[i])
maxfd = client_fd[i];
}
ret = ::select(maxfd + 1, &fdReads, NULL, NULL, NULL);
#endif
if (ret > 0)
{
for (i = 0; i < MAX_CLIENT_NUM; i++)
{
if (FD_ISSET(client_fd[i], &fdReads))
{
if (client_fd[i] == m_fdListen)
{
if (nClientCount < MAX_CLIENT_NUM)
{
net_socket_fd fdAccept = NET_INVALID_SOCKET;
pEvent->OnAccept(fdAccept);
if (fdAccept != NET_INVALID_SOCKET)
{
for (j = 1; j < MAX_CLIENT_NUM; j++)
{
if (client_fd[j] == -1)
{
client_fd[j] = fdAccept;
FD_SET(fdAccept, &m_fdSocket);
nClientCount++;
break;
}
}
}
}
else
{
pError->OnError(ERROR_SELECT_MAXFD, ELEVEL_WARNING);
}
}
else
{
if (pEvent->OnRead(client_fd[i]) != 0)
{
if (pEvent->OnClose(client_fd[i]) != 0)
closesocket(client_fd[i]);
FD_CLR(client_fd[i], &m_fdSocket);
client_fd[i] = -1;
nClientCount--;
}
}
}
}
}
else
{
if (pError->OnError(ELEVEL_ERROR) != 0)
break;
}
}
return ret;
}
测试文件main.cpp
#include <iostream>
#include "Platform.h"
#include "SocketImpl.h"
#include "MyError.h"
#include "MyExit.h"
#include "MySelectEvent.h"
#include "Select.h"
using namespace std;
int main(int argc, char* argv[])
{
LinWin::CSocketAddress addr(NET_DEFAULT_IP, 6666);
LinWin::CSocketImpl server;
do
{
if (server.Create() != 0)
{
cout << "Create socket error." << endl;
break;
}
if (server.Bind(addr) != 0)
{
cout << "Bind address errror." << endl;
break;
}
if (server.Listen(2) != 0)
{
cout << "Listen error." << endl;
break;
}
LinWin::CSelectImpl mySelect(server.Sockfd());
CMyError myError;
CMyExit myExit;
CMySelectEvent mySelectEvent(&server, &myExit);
mySelect.Select(&mySelectEvent, &myError, &myExit);
} while (0);
return 0;
}
测试程序给出的是服务器端的例子,客户端还可以用之前给出的客户端的例子。