zoukankan      html  css  js  c++  java
  • C++ Windows 上简单的非阻塞Select模型

    说明:当客户端连接数超过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 + 1 > maxfdp){ maxfdp = fd + 1; }
        }
        void FDZero()
        { 
            FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&errorfds); 
            maxfdp = 0;
        }
        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 = 0;
        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, 5);
        if (nRet != S_OK){ return WSAGetLastError(); }
        printf("listen:%d
    ", sListen);
        return S_OK;
    }
    
    void CModuleSelect::ProcessEvent(uint32_t nTimeUsec)
    {
        int32_t nRet = S_OK;
        static struct timeval timeout;
        timeout.tv_sec = nTimeUsec / 1000000;
        timeout.tv_usec = nTimeUsec % 1000000;
    
        static int32_t addrSize = sizeof(SOCKADDR_IN);
        static char buf[1024];
        static SOCKADDR_IN addrRemote;
        // select all used fd
        uint32_t unStartPos = 0, unEndPos = 0;
        do
        {
            // reset fd_set
            FDZero();
            // fd_set size limited by 'FD_SETSIZE'
            for (uint32_t i = 0; i < FD_SETSIZE && unEndPos < unFdSize; ++i)
            {
                FDSet(arrFd[unEndPos++]);
            }
            nRet = select(maxfdp, &readfds, &writefds, &errorfds, &timeout);
            // select error
            if (nRet == -1)
            {
                int32_t nError = WSAGetLastError();
                perrors("select error,nRet=%d,info=%s
    ", nError, strerror(nError));
                exit(1);
            }
            // time out ,nothing happened
            else if (nRet == 0)
            {
                printf(".");
                continue;
            }
            // some thing happened
            else if (nRet > 0)
            {
                // check events
                for (uint32_t i = unStartPos; i < unEndPos; ++i)
                {
                    // read events
                    if ( FD_ISSET(arrFd[i],&readfds) )
                    {
                        printf("[%d]:read = %d
    ",i,arrFd[i]);
                        if (sListen == arrFd[i])
                        {
                            nRet = accept(sListen, (struct sockaddr*)&addrRemote, &addrSize);
                            printf("Accepted client:%s:%d
    ", inet_ntoa(addrRemote.sin_addr), ntohs(addrRemote.sin_port));
                            AddFd(nRet);
                        }
                        else
                        {
                            nRet = recv(arrFd[i], buf, 1024, 0);
                            if (nRet == 0 || nRet == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
                            {
                                // client close
                                DelFd(i);
                            }
                            else
                            {
                                // received correct data from client
                                buf[nRet] = '';
                                send(arrFd[i], buf, strlen(buf), 0);
                            }
                        }
                    }
                    // write events
                    else if (FD_ISSET(arrFd[i], &writefds))
                    {
                        Sleep(1);
                        //printf("write = %d
    ", arrFd[i]);
                    }
                    // error events
                    else if (FD_ISSET(arrFd[i], &errorfds))
                    {
                        printf("error = %d
    ", 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 -1;
    }
    
    int32_t CModuleSelect::DelFd(uint32_t index)
    {
        if (unFdSize > 1 && index > 0 && unFdSize > index)
        {
            closesocket(arrFd[index]);
            arrFd[index] = arrFd[unFdSize - 1];
            --unFdSize;
        }
        return S_OK;
    }
  • 相关阅读:
    339. Nested List Weight Sum
    41. First Missing Positive
    366. Find Leaves of Binary Tree
    287. Find the Duplicate Number
    130. Surrounded Regions
    ubuntu18.04安装mongodb4.4
    阿里dataX配置使用
    MySQL主从同步简单介绍&配置
    阿里yugong配置使用
    ubuntu编译安装mysql
  • 原文地址:https://www.cnblogs.com/tangxin-blog/p/5722828.html
Copyright © 2011-2022 走看看