尝试新思路——跨平台Select模型

来源:互联网 发布:淘宝moschino 编辑:程序博客网 时间:2024/06/07 23:44

Select模型头文件

#ifndef __SELECT_H__#define __SELECT_H__#define ERROR_SELECT_MAXFD    1#define ERROR_SELECT_INVALID  2#define ERROR_SELECT_SOCKET   3namespace 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 16LinWin::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;}

测试程序给出的是服务器端的例子,客户端还可以用之前给出的客户端的例子。

0 0
原创粉丝点击