因为要在服务内集成一个提供状态数据的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;
}