#include <stdio.h>
#ifdef WIN32
#include <winsock.h>
typedef int socklen_t;
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <arpa/inet.h>
typedef int SOCKET;
//#pragma region define win32 const variable in linux
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
//#pragma endregion
#endif
#define None_SocketID -1
#define MaxClient 8000
class CSocket
{
public:
CSocket();
CSocket(int socketId);
~CSocket();
bool init(); //don't reCreate, memoryPool
bool host(int port = 6898);
bool connect(const char* address, bool );
void close();
bool recv();
bool send();
static void printError(){};
public:
int m_iSocketID = None_SocketID;
};
CSocket::CSocket()
{
}
CSocket::CSocket(int socketId)
{
m_iSocketID = socketId;
}
CSocket::~CSocket()
{
close();
}
void CSocket::close()
{
if(m_iSocketID >=0)
{
::close(m_iSocketID);
m_iSocketID = None_SocketID;
}
}
bool CSocket::init()
{
if(m_iSocketID < 0)
{
m_iSocketID = socket(AF_INET, SOCK_STREAM, 0);
if(m_iSocketID < 0)
{
m_iSocketID = None_SocketID;
printError();
return false;
}
}
return true;
}
bool CSocket::host(int port)
{
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
sa.sin_addr.s_addr = INADDR_ANY;
if(bind(m_iSocketID, (struct sockaddr*)&sa, sizeof(sa)) < 0)
{
printError();
return false;
}
if(listen(m_iSocketID, 100) < 0)
{
printError();
return false;
}
return true;
}
bool CSocket::connect(const char* address, bool )
{
struct sockaddr_in s_addr_in;
s_addr_in.sin_family = AF_INET;
s_addr_in.sin_port = htons(6898);
s_addr_in.sin_addr.s_addr = inet_addr(address);
if(::connect(m_iSocketID, (struct sockaddr*)&s_addr_in, sizeof(s_addr_in)) < 0)
{
printError();
return false;
}
return true;
}
bool CSocket::recv()
{
char read_buf[1024];
int size = 1024;
int recvSize;
recvSize = ::recv(m_iSocketID, read_buf, size, 0);
if(recvSize == 0)
return false;
#ifdef EINTR
if(errno_t == EINTR)
return true;
#endif
#ifdef EAGAIN
if(errno_t == EAGAIN)
return true;
#endif
#ifdef EWOULBLOCK
if(errno_t == EWOULDBLOCK)
return true;
#endif
return true;
}
bool CSocket::send()
{
int sendSize;
return true;
}
typedef CSocket Client;
#define Log printf
class Server
{
public:
Server();
~Server();
bool init();
bool run();
void close();
protected:
//void Log(const char* str){}
protected:
CSocket* m_pServerSocket = nullptr;
int m_iMaxSocketId = None_SocketID;
Client* m_vClients = nullptr;
int m_numClient = 0;
};
Server::Server()
{
init();
}
Server::~Server()
{
close();
}
bool Server::init()
{
if(!m_pServerSocket)
{
m_pServerSocket = new CSocket;
if(!m_pServerSocket->init())
{
Log("create server error\n");
return false;
}
if(!m_pServerSocket->host(7878))
{
Log("host server error\n");
return false;
}
Log("host server success\n");
}
if(!m_vClients)
{
m_vClients = new Client[MaxClient];
}
return true;
}
bool Server::run()
{
struct sockaddr addr;
socklen_t size;
Client* pNewClient = nullptr;
int newClient;
while(1)
{
newClient = accept(m_pServerSocket->m_iSocketID, &addr, &size);
if(newClient >= 0)
{
if(m_numClient == MaxClient)
{
Log("service full\n");
continue;
}
m_vClients[m_numClient++].init();
m_vClients[m_numClient-1].m_iSocketID = newClient;
Log("new Client connect: %d\n", newClient);
// if(newClient > m_iMaxSocketId) m_iMaxSocketId = newClient;
}
//selected
fd_set read_set, exc_set;
struct timeval tv;
struct sockaddr_in sa;
int nfds, i, sa_size;
char recvBuffer[1024];
sa_size = sizeof(sa);
tv.tv_sec = tv.tv_usec = 0;
FD_ZERO(&read_set);
FD_ZERO(&exc_set);
FD_SET(m_pServerSocket->m_iSocketID, &read_set);
m_iMaxSocketId = 0;
for(i = 0; i < m_numClient; ++ i)
{
if(m_vClients[i].m_iSocketID != None_SocketID)
{
if(m_vClients[i].m_iSocketID > m_iMaxSocketId)
m_iMaxSocketId = m_vClients[i].m_iSocketID;
FD_SET(m_vClients[i].m_iSocketID, &read_set);
FD_SET(m_vClients[i].m_iSocketID, &exc_set);
}
}
if(select(m_iMaxSocketId + 1, &read_set, nullptr, &exc_set, &tv) == -1)
{
Client::printError();
Log("select error\n");
continue;
}
for(i = 0; i < m_numClient; ++ i)
{
if(m_vClients[i].m_iSocketID == None_SocketID) continue;
if(FD_ISSET(m_vClients[i].m_iSocketID, &exc_set))
{
FD_CLR(m_vClients[i].m_iSocketID, &read_set);
FD_CLR(m_vClients[i].m_iSocketID, &exc_set);
m_vClients[i].close();
Client tmp = m_vClients[i];
m_vClients[i] = m_vClients[m_numClient - 1];
m_vClients[m_numClient-1] = tmp;
m_numClient --;
if(i != m_numClient) i--;
continue;
}
if(FD_ISSET(m_vClients[i].m_iSocketID, &read_set))
{
if(!m_vClients[i].recv())
{
FD_CLR(m_vClients[i].m_iSocketID, &read_set);
FD_CLR(m_vClients[i].m_iSocketID, &exc_set);
m_vClients[i].close();
Client tmp = m_vClients[i];
m_vClients[i] = m_vClients[m_numClient - 1];
m_vClients[m_numClient-1] = tmp;
m_numClient --;
if(i != m_numClient) i--;
continue;
}
m_pServerSocket[i]->send("ok");
}
}
}
return true;
}
void Server::close()
{
if(m_pServerSocket)
{
delete m_pServerSocket;
m_pServerSocket = nullptr;
}
}
int main(int argc, const char * argv[])
{
Server* pServer = new Server;
pServer->run();
return 0;
}