因为要在服务内集成一个提供状态数据的http监控服务,而封装的一个select io


#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <pthread.h>


#define MYPORT 4894    // the port users will be connecting to
#define BACKLOG 32     // how many pending connections queue will hold
#define BUF_SIZE 1024


class CSelectServer
{
public:
    CSelectServer()
    {
    }

    ~CSelectServer()
    {
        stop();
    }    

    struct SHORT_SESSION 
    {
        int m_uClientSockfd;
        int m_uTimestamp;
    };
    
    bool start(int nPort)
    {
        int ret=0;

        do 
        {
            m_uListenPort=nPort;
            m_hListenSockfd= socket( PF_INET, SOCK_STREAM, 0 );
            if (m_hListenSockfd < 0)
            {
                break;
            }

            struct sockaddr_in address;
            bzero( &address, sizeof( address ) );
            address.sin_family = AF_INET;
            address.sin_port = htons( m_uListenPort );

            ret = bind( m_hListenSockfd, ( struct sockaddr* )&address, sizeof( address ) );
            if (ret < 0)
            {
                break;
            }

            ret = listen( m_hListenSockfd, BACKLOG );
            if (ret < 0)
            {
                break;
            }    

            m_hMaxSockfd=m_hListenSockfd;
            m_uConnAmount=0;
            for (int i=0;i<BACKLOG;++i)
            {
                m_nClientConns[i].m_uClientSockfd=-1;
                m_nClientConns[i].m_uTimestamp=0;
            }
            
            // timeout setting
            m_tvSelectDelay.tv_sec = 1;
            m_tvSelectDelay.tv_usec = 0;

            
            return true;
        } while (0);

        stop();
        return false;
    }

    void stop()
    {
        if (-1 != m_hListenSockfd)
        {
            close(m_hListenSockfd);
            m_hListenSockfd=-1;
        }
    }

    void serve_once()
    {    
        int ret,i;    
        int now=(int)time(NULL);

        FD_ZERO(&m_hReadfds);
        FD_SET(m_hListenSockfd, &m_hReadfds);

        for ( i = 0; i < BACKLOG; i++)
        {
            if (m_nClientConns[i].m_uClientSockfd<=2)
                continue;

            if (now>=m_nClientConns[i].m_uTimestamp+5) 
            {
                printf("kickoutDeadConnection sock:%d conn_amount:%d\n",m_nClientConns[i].m_uClientSockfd,m_uConnAmount);
                FD_CLR(m_nClientConns[i].m_uClientSockfd, &m_hReadfds);
                close(m_nClientConns[i].m_uClientSockfd);
                m_nClientConns[i].m_uClientSockfd=-1;
                m_uConnAmount--;
                continue;
            }

            FD_SET(m_nClientConns[i].m_uClientSockfd, &m_hReadfds);
        }

        ret = select(m_hMaxSockfd + 1, &m_hReadfds, NULL, NULL, &m_tvSelectDelay);
        if (ret < 0)
        {
            perror("select error\n");
            return;
        }
        
        if (ret == 0)
        {
            printf("select maxsock:%d timeout\n",m_hMaxSockfd);
            return;
        }

        // check whether a new connection comes
        if (FD_ISSET(m_hListenSockfd, &m_hReadfds))
        {
            printf("will accept\n");
            struct sockaddr_in client_address;
            socklen_t client_addrlength = sizeof( client_address );
            int new_fd = accept( m_hListenSockfd, ( struct sockaddr* )&client_address, &client_addrlength );
            if (new_fd <= 0)
            {
                perror("accept");
            }
            else
            {
                printf("accept sock:%d\n",new_fd);
                addConnection(new_fd);
            }
        }

        // check every fd in the set
        for ( i = 0; i < BACKLOG; i++)
        {
            if (-1==m_nClientConns[i].m_uClientSockfd)
                continue;

            if (FD_ISSET(m_nClientConns[i].m_uClientSockfd, &m_hReadfds)) 
            {
                printf("client[%d] will recv\n", m_nClientConns[i].m_uClientSockfd);

                ret = recv(m_nClientConns[i].m_uClientSockfd, m_szReadBuffer, sizeof(m_szReadBuffer), 0);
                if (ret <= 0) 
                {        
                    printf("delConnection sock:%d conn_amount:%d\n",m_nClientConns[i].m_uClientSockfd,m_uConnAmount);
                    FD_CLR(m_nClientConns[i].m_uClientSockfd, &m_hReadfds);
                    close(m_nClientConns[i].m_uClientSockfd);
                    m_nClientConns[i].m_uClientSockfd=-1;
                    m_uConnAmount--;
                } 
                else 
                { 
                    printf("client[%d] send:%s\n", m_nClientConns[i].m_uClientSockfd, m_szReadBuffer);
                    send(m_nClientConns[i].m_uClientSockfd,m_szReadBuffer,ret,0);
                }
            }
        }

    }
protected:
    bool addConnection(int client_fd)
    {
        do 
        {
            if (m_uConnAmount>=BACKLOG)
            {
                printf("addConnection over the limit \n");
                break;
            }

            int i;
            for ( i = 0; i < BACKLOG; i++) 
            {
                if (-1==m_nClientConns[i].m_uClientSockfd) 
                {
                    m_nClientConns[i].m_uClientSockfd=client_fd;
                    m_nClientConns[i].m_uTimestamp=(int)time(NULL);
                    m_uConnAmount++;
                    printf("addConnection  sock:%d conn_amount:%d \n",client_fd,m_uConnAmount);
                    if (client_fd>m_hMaxSockfd)
                    {
                        m_hMaxSockfd=client_fd;
                    }
                    return true;
                }
            }
            
            printf("addConnection system error\n");
        } while (0);

        return false;        
    }

    void delConnection(int client_fd)
    {
        int i;
        for ( i = 0; i < BACKLOG; i++) 
        {
            if (client_fd==m_nClientConns[i].m_uClientSockfd) 
            {
                FD_CLR(m_nClientConns[i].m_uClientSockfd, &m_hReadfds);
                close(m_nClientConns[i].m_uClientSockfd);
                m_nClientConns[i].m_uClientSockfd=-1;
                m_uConnAmount--;
                //printf("delConnection sock:%d conn_amount:%d\n",client_fd,m_uConnAmount);
                return ;
            }
        }
        //printf("delConnection system error\n");

    }

    void kickoutDeadConnection()
    {
        int now=(int)time(NULL);
        int i;
        for ( i = 0; i < BACKLOG; i++) 
        {
            if (-1==m_nClientConns[i].m_uClientSockfd) 
            {
                continue;
            }

            if (now>=m_nClientConns[i].m_uTimestamp+5) 
            {
                //printf("kickoutDeadConnection sock:%d conn_amount:%d\n",m_nClientConns[i].m_uClientSockfd,m_uConnAmount);
                FD_CLR(m_nClientConns[i].m_uClientSockfd, &m_hReadfds);
                close(m_nClientConns[i].m_uClientSockfd);
                m_nClientConns[i].m_uClientSockfd=-1;
                m_uConnAmount--;
            }

        }
    }

private:
    SHORT_SESSION    m_nClientConns[BACKLOG];
    char             m_szReadBuffer[BUF_SIZE];
    int                 m_uListenPort;
    int                 m_hListenSockfd;
    int                 m_uConnAmount;
    int                 m_hMaxSockfd;
    fd_set             m_hReadfds;
    struct timeval   m_tvSelectDelay;
    
};













int main( int argc, char* argv[] )
{
    if( argc <= 2 )
    {
        printf( "usage: %s ip_address port_number\n", basename( argv[0] ) );
        return 1;
    }
    const char* ip = argv[1];
    int port = atoi( argv[2] );

    //CSimpleEpollServer  s;
    CSelectServer s;
    s.start(port);

    while (1)
    {
        s.serve_once();
        usleep(1000*1000);
    }
    

   
    return 0;
}


集成到系统之后 的代码: (有修改)

#include 
"datatype.h"
#include 
<sys/types.h>
#include 
<sys/socket.h>
#include 
<netinet/in.h>
#include 
<arpa/inet.h>
#include 
<stdio.h>
#include 
<unistd.h>
#include 
<errno.h>
#include 
<string.h>
#include 
<stdlib.h>

class CMonitorHttpService
{
public:
    CMonitorHttpService();
    
~CMonitorHttpService(){stop();}    
    
bool start(uint32 nPort,uint32 nClientTimeout=5);    
    
void stop();
    
void serve_once();    
    typedef 
void (*PFUNC_GET_STATICTISDATA)(char*& apPtrRef,uint32& auDataLen);
    
void setGetStatictisDataHandler(PFUNC_GET_STATICTISDATA apGetStatictisDataHandler);
protected:
    
bool addConnection(int client_fd);    
    
void delConnection(int client_fd);
    
void kickoutDeadConnection();
    
void tellStatictisData( int client_fd);
    
struct SHORT_SESSION 
    
{
        
int m_uClientSockfd;
        
int m_uTimestamp;
    }
;
private:
    
const static int MAX_MON_READ_BUF_SIZE=1024;
    
const static int MAX_ALLOW_MONITOR_COUNT=32;
    SHORT_SESSION    m_nClientConns[MAX_ALLOW_MONITOR_COUNT];
    
char             m_szReadBuffer[MAX_MON_READ_BUF_SIZE];
    uint32             m_uListenPort;
    
int                 m_hListenSockfd;
    uint32           m_uClientTimeout;
    int32             m_uConnAmount;
    
int                 m_hMaxSockfd;
    fd_set             m_hReadfds;
    
struct timeval   m_tvSelectDelay;
    PFUNC_GET_STATICTISDATA mpGetStatictisDataHandler;

}
;






#include 
"monitor_httpservice.h"
#include 
"StringBuffer.h"
#include 
"Debug_log.h"






CMonitorHttpService::CMonitorHttpService()
{
    mpGetStatictisDataHandler
=NULL;
    m_hListenSockfd
=-1;
}


bool CMonitorHttpService::start( uint32 nPort ,uint32 nClientTimeout)
{
    
const char* lpszLog="";
    
int ret=0;

    
do 
    
{
        m_uListenPort
=nPort;
        m_uClientTimeout
=nClientTimeout;

        m_hListenSockfd
= socket( PF_INET, SOCK_STREAM, 0 );
        
if (m_hListenSockfd < 0)
        
{
            lpszLog
="socket() failed";
            
break;
        }


        
int liReuseaddr=1;
        ret 
= setsockopt(m_hListenSockfd,SOL_SOCKET ,SO_REUSEADDR,(const char*)&liReuseaddr,sizeof(liReuseaddr));
        
if (ret < 0)
        
{
            lpszLog
="setsockopt SO_REUSEADDR failed";
            
break;
        }


        
struct sockaddr_in address;
        bzero( 
&address, sizeof( address ) );
        address.sin_family 
= AF_INET;
        address.sin_port 
= htons( m_uListenPort );

        ret 
= bind( m_hListenSockfd, ( struct sockaddr* )&address, sizeof( address ) );
        
if (ret < 0)
        
{
            lpszLog
="bind() failed";
            
break;
        }


        ret 
= listen( m_hListenSockfd, MAX_ALLOW_MONITOR_COUNT );
        
if (ret < 0)
        
{
            lpszLog
="listen() failed";
            
break;
        }
    

        m_hMaxSockfd
=m_hListenSockfd;
        m_uConnAmount
=0;
        
for (int i=0;i<MAX_ALLOW_MONITOR_COUNT;++i)
        
{
            m_nClientConns[i].m_uClientSockfd
=-1;
            m_nClientConns[i].m_uTimestamp
=0;
        }


        
// timeout setting
        m_tvSelectDelay.tv_sec = 1;
        m_tvSelectDelay.tv_usec 
= 0;

        LOG_TRACE(LOG_DEBUG, 
true, __PRETTY_FUNCTION__, " "
            
<<" nPort:"<<nPort
            
<<" uClientTimeout:"<<m_uClientTimeout
            ) ;

        
return true;
    }
 while (0);

    LOG_TRACE(LOG_CRIT, 
false, __PRETTY_FUNCTION__, " "
        
<<" nPort:"<<nPort
        
<<" lpszLog:"<<lpszLog
        ) ;

    stop();
    
return false;
}


void CMonitorHttpService::stop()
{
    
if (m_hListenSockfd<=2)
    
{
        close(m_hListenSockfd);
        m_hListenSockfd
=-1;
    }

}


void CMonitorHttpService::serve_once()
{    
    
if (m_hListenSockfd<=2)
    
{
        
return ;
    }


    
int ret,i;    
    
int now=(int)time(NULL);

    FD_ZERO(
&m_hReadfds);
    FD_SET(m_hListenSockfd, 
&m_hReadfds);

    
for ( i = 0; i < MAX_ALLOW_MONITOR_COUNT; i++)
    
{
        
if (m_nClientConns[i].m_uClientSockfd<=2)
            
continue;

        
if (now>=m_nClientConns[i].m_uTimestamp+m_uClientTimeout) 
        
{
            LOG_TRACE(LOG_NOTICE, 
true, __PRETTY_FUNCTION__, " timeout,kickoutDeadConnection "
                
<<" sock:"<<m_nClientConns[i].m_uClientSockfd
                
<<" m_uConnAmount:"<<m_uConnAmount
                ) ;

            close(m_nClientConns[i].m_uClientSockfd);
            m_nClientConns[i].m_uClientSockfd
=-1;
            m_uConnAmount
--;
            
continue;
        }


        FD_SET(m_nClientConns[i].m_uClientSockfd, 
&m_hReadfds);
    }


    ret 
= select(m_hMaxSockfd + 1&m_hReadfds, NULL, NULL, &m_tvSelectDelay);
    
if (ret < 0)
    
{
        LOG_TRACE(LOG_ERR, 
false, __PRETTY_FUNCTION__, " select error "
            
<<" m_hMaxSockfd:"<<m_hMaxSockfd
            
<<" m_uConnAmount:"<<m_uConnAmount
            ) ;
        
return;
    }


    
if (ret == 0)
    
{
        
return;
    }


    
// check whether a new connection comes
    if (FD_ISSET(m_hListenSockfd, &m_hReadfds))
    
{
        
struct sockaddr_in client_address;
        socklen_t client_addrlength 
= sizeof( client_address );
        
int new_fd = accept( m_hListenSockfd, ( struct sockaddr* )&client_address, &client_addrlength );
        
if (new_fd <= 0)
        
{
            LOG_TRACE(LOG_ERR, 
false, __PRETTY_FUNCTION__, " accept error "
                
<<" m_hMaxSockfd:"<<m_hMaxSockfd
                
<<" m_uConnAmount:"<<m_uConnAmount
                ) ;
        }

        
else
        
{
            addConnection(new_fd);
        }

    }


    
// check every fd in the set
    for ( i = 0; i < MAX_ALLOW_MONITOR_COUNT; i++)
    
{
        
if (m_nClientConns[i].m_uClientSockfd<=2)
            
continue;

        
if (FD_ISSET(m_nClientConns[i].m_uClientSockfd, &m_hReadfds)) 
        
{
            ret 
= recv(m_nClientConns[i].m_uClientSockfd, m_szReadBuffer, sizeof(m_szReadBuffer), 0);
            
if (ret <= 0
            
{   
                LOG_TRACE(LOG_ERR, 
false, __PRETTY_FUNCTION__, " delConnection "
                    
<<" client_fd:"<<m_nClientConns[i].m_uClientSockfd
                    ) ;

                close(m_nClientConns[i].m_uClientSockfd);
                m_nClientConns[i].m_uClientSockfd
=-1;
                m_uConnAmount
--;
            }
 
            
else 
            

                tellStatictisData(m_nClientConns[i].m_uClientSockfd);
            }

        }

    }


}


bool CMonitorHttpService::addConnection( int client_fd )
{
    
do 
    
{
        
if (m_uConnAmount>=MAX_ALLOW_MONITOR_COUNT)
        
{
            LOG_TRACE(LOG_WARNING, 
false, __PRETTY_FUNCTION__, "accept is overload  "
                
<<" m_hMaxSockfd:"<<m_hMaxSockfd
                
<<" m_uConnAmount:"<<m_uConnAmount
                
<<" client_fd:"<<client_fd
                ) ;
            
break;
        }


        
int i;
        
for ( i = 0; i < MAX_ALLOW_MONITOR_COUNT; i++
        
{
            
if (-1==m_nClientConns[i].m_uClientSockfd) 
            
{
                m_nClientConns[i].m_uClientSockfd
=client_fd;
                m_nClientConns[i].m_uTimestamp
=(int)time(NULL);
                m_uConnAmount
++;
                
                LOG_TRACE(LOG_DEBUG, 
true, __PRETTY_FUNCTION__, ""
                    
<<" m_hMaxSockfd:"<<m_hMaxSockfd
                    
<<" m_uConnAmount:"<<m_uConnAmount
                    
<<" client_fd:"<<client_fd
                    ) ;

                
if (client_fd>m_hMaxSockfd)
                
{
                    m_hMaxSockfd
=client_fd;
                }

                
return true;
            }

        }


        LOG_TRACE(LOG_CRIT, 
false, __PRETTY_FUNCTION__, " system error "
            
<<" m_hMaxSockfd:"<<m_hMaxSockfd
            
<<" m_uConnAmount:"<<m_uConnAmount
            
<<" client_fd:"<<client_fd
            ) ;    
    }
 while (0);

    
return false;        
}


void CMonitorHttpService::delConnection( int client_fd )
{
    
int i;
    
for ( i = 0; i < MAX_ALLOW_MONITOR_COUNT; i++
    
{
        
if (client_fd==m_nClientConns[i].m_uClientSockfd) 
        
{
            close(m_nClientConns[i].m_uClientSockfd);
            m_nClientConns[i].m_uClientSockfd
=-1;
            m_uConnAmount
--;
            
//printf("delConnection sock:%d conn_amount:%d\n",client_fd,m_uConnAmount);
            return ;
        }

    }

    
//printf("delConnection system error\n");

}


void CMonitorHttpService::kickoutDeadConnection()
{
    
int now=(int)time(NULL);
    
int i;
    
for ( i = 0; i < MAX_ALLOW_MONITOR_COUNT; i++
    
{
        
if (-1==m_nClientConns[i].m_uClientSockfd) 
        
{
            
continue;
        }


        
if (now>=m_nClientConns[i].m_uTimestamp+5
        
{
            close(m_nClientConns[i].m_uClientSockfd);
            m_nClientConns[i].m_uClientSockfd
=-1;
            m_uConnAmount
--;
        }


    }

}



void CMonitorHttpService::setGetStatictisDataHandler( PFUNC_GET_STATICTISDATA apGetStatictisDataHandler )
{
    mpGetStatictisDataHandler
=apGetStatictisDataHandler;
}


//只能在一个线程里跑,设定在主线程里跑,并发量控制在32个以内。
void CMonitorHttpService::tellStatictisData( int client_fd)
{
    
const static uint32  MAX_STATISTICDATA_SIZE  = 9*1024 ;
    
static CStringBuffer<MAX_STATISTICDATA_SIZE> httpbuf ;

    
char*  ptr=NULL;
    uint32 len
=0;
    
int    ret=0;
    httpbuf.Clear();
    
    
if (NULL == mpGetStatictisDataHandler)
    
{
        
return ;
    }


    mpGetStatictisDataHandler(ptr,len);

    
if (len>0 && ptr !=NULL)
    
{
        httpbuf.AddString( 
"HTTP/1.1 200 OK\r\n") ;
        httpbuf.AddString( 
"Content-Type: text/html;charset=ISO-8859-1\r\n") ;
        httpbuf.AddFormat( 
"Content-Length:%u\r\n",len);
        httpbuf.AddFormat( 
"\r\n\r\n");
        httpbuf.AddBuffer(ptr,len);
        ret
=send(client_fd,httpbuf.GetBuffer(), httpbuf.GetLength(),0);
        
if (ret <= 0)
        
{
            LOG_TRACE(LOG_ERR, 
false, __PRETTY_FUNCTION__, " send() faield"
                
<<" m_hMaxSockfd:"<<m_hMaxSockfd
                
<<" m_uConnAmount:"<<m_uConnAmount
                
<<" client_fd:"<<client_fd
                ) ;    
        }

    }

}







1