#define UDP 1
#define THREAD_STACK_SIZE 1*1024*1024
//using namespace std
//using std::string;
typedef struct client_t
{
int sockfd;
}myclient;
class abstractserver
{
public:
int msockfd;//server sockfd
int mserverport;
int mtimeout;
int mtransmode;
char *mserverip;
char *mhostname;//域名
char *mclientip;
char *msendbuf;
char *mrecvbuf;
int mNeedSend;//要发送的数据
int mRecvBufLen;//接受缓冲区大小
//static void (*callbackserver) (void *argv);//服务器处理函数
public:
abstractserver(int port, char *serip, char *hostname,int t_mode);
virtual ~abstractserver(void);
bool init_socket();
void Close(int sockfd);
void SetBlock(bool bblock,int sockfd);
bool Checktimeout(bool isread,int sockfd);
bool AcceptClient(void);
int create_client_thread(myclient *m_client);
int SendData(int sockfd);
int RecvDate(int sockfd);
//static void realthread(void *arg);
//virtual bool SendCommand(const char* szMessage)=0;
};
#include"common.h"
#include "abstractserver.h"
#if 0
#ifdef __cplusplus
extern "C"{
#endif
extern void server_thread(void *argv);// in xxx.c file
#ifdef __cplusplus
}
#endif
#else
extern void server_thread(void *argv);// in xxx.cpp file
#endif
void *realthread(void *arg)
{
server_thread(arg);
return (void *)NULL;
}
// this is a tcp server demo
abstractserver::abstractserver(int port, char *serip,char *hostname, int t_mode)
{
mserverport = port;
mtransmode = t_mode;
mtimeout = 10;//10 sec
msockfd = -1;
mserverip = NULL;
mhostname = NULL;
mRecvBufLen = 0;
mNeedSend = 0;
msendbuf = NULL;
mrecvbuf = NULL;
if(serip!=NULL)
{
mserverip = (char *)malloc(32);
if(mserverip)
{
snprintf(mserverip,32,"%s",serip);
}
}
if( hostname!=NULL)
{
mhostname = (char *)malloc(128);
if(mhostname)
{
snprintf(mhostname,128,"%s",hostname);
}
}
}
abstractserver::~abstractserver(void)
{
if(mserverip!=NULL)
{
free((void *)mserverip);
}
if(mhostname!=NULL)
{
free((void *)mhostname);
}
//Close();
printf("release abstractclient !\n");
}
void abstractserver::Close(int sockfd)
{
#ifdef Linux
if(sockfd >= 0)
{
shutdown(sockfd,SHUT_WR);
close(sockfd);
}
#elif _WIN32_WINNT
if(sockfd >= 0)
{
shutdown(sockfd,SD_SEND);
closesocket(sockfd);
}
#endif
sockfd = -1;
}
//设置网络套接字阻塞或者非阻塞
void abstractserver::SetBlock(bool bblock,int sockfd)
{
#ifdef Linux
int mode = bblock ? 0 : 1;
ioctl(sockfd, FIONBIO, &mode); //设置为非阻塞模式
#elif _WIN32_WINNT
unsigned long op = bblock ? 0 : 1;
if (ioctlsocket(sockfd, FIONBIO, &op) == SOCKET_ERROR)
{
printf("Unable to Set Blocking");
}
#endif
}
//判断网络是否超时
bool abstractserver::Checktimeout(bool isread,int sockfd)
{
int len;
fd_set writeset;
fd_set readset;
fd_set *fdset = NULL;
struct timeval tm;
len = sizeof(int);
tm.tv_sec = mtimeout;
tm.tv_usec = 0;
FD_ZERO(&readset);
FD_ZERO(&writeset);
if(isread)
{
FD_SET(sockfd, &readset);
fdset = &readset;
}
else
{
FD_SET(sockfd, &writeset);
fdset = &writeset;
}
/* 等待连接,如果超时(10s),那么返回连接错误 by wangjidong*/
if (select(sockfd + 1,&readset,&writeset, NULL, &tm) > 0)
{
if(FD_ISSET(sockfd,fdset))
{
return false;
}
else
{
return true;
}
}
else
{
return true;
}
return false;
}
// 初始化socket
bool abstractserver::init_socket()
{
if(mtransmode == UDP)
{
msockfd = socket(AF_INET, SOCK_DGRAM, 0);
}
else
{
msockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
}
if (0 > msockfd)
{
return false;
}
struct sockaddr_in server; //服务器地址信息结构体
memset(&server,0,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(mserverport);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(msockfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1)
{ //调用bind绑定地址
perror("Bind error.");
return false;
}
if(listen(msockfd,10) == -1)
{ //调用listen开始监听
perror("listen() error\n");
return false;
}
unsigned int nBufferSize = 40960;
unsigned int nBufferSize2 = 40960;
int reuse = true;
setsockopt(msockfd, SOL_SOCKET, SO_SNDBUF, (char *)&nBufferSize2, sizeof(nBufferSize2));
setsockopt(msockfd, SOL_SOCKET, SO_RCVBUF, (char *)&nBufferSize, sizeof(nBufferSize));
setsockopt(msockfd,SOL_SOCKET ,SO_REUSEADDR,(char *)&reuse,sizeof(int));
/*设置socket 阻塞模式发送接收数据*/
//阻塞模式http 协议数据够用
SetBlock(true,msockfd);
return true;
}
// try connect server ,first init sock, then connect server
bool abstractserver::AcceptClient(void)
{
if(init_socket()==false)
{
return false;
}
int clientfd;
struct sockaddr_in Clientaddr;
int sin_size = sizeof(Clientaddr);
while(1)
{
if(Checktimeout(true,msockfd))
{
printf("Checktimeout @@@ in AcceptClient\n");
continue;
}
if ((clientfd = accept(msockfd,(struct sockaddr *)&Clientaddr,(socklen_t *)&sin_size))== -1)
{
printf("accept() error\n");
continue;
}
printf("accept a client is %s \n",inet_ntoa(Clientaddr.sin_addr));
myclient *m_client = (myclient *)malloc(sizeof(myclient));
if(m_client != NULL)
{
m_client->sockfd = clientfd;
create_client_thread(m_client);
}
else
{
Close(clientfd);
}
}
return true;
}
int abstractserver::create_client_thread(myclient *m_client)
{
if(m_client ==NULL )
{
return -1;
}
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
//*callbackclient must free the client the struct*//
int ret = pthread_create(&tid, &attr, realthread,(void*) m_client);
if (ret != 0)
{
printf("create thread cloud_msg_handle_thread fail, ret %d \n", ret);
Close(m_client->sockfd);
if(m_client != NULL)
{
free((void *)m_client);
}
return -1;
}
return tid;
}
int abstractserver::SendData(int sockfd)
{
if(msendbuf == NULL || mNeedSend <= 0)
{
return -1;
}
bool is_read = false;
if(Checktimeout(is_read,sockfd))
{
return -1;
}
int ret = send(sockfd,msendbuf,mNeedSend,0);
// ret <= 0 is false
mNeedSend = 0;
msendbuf = NULL;
return ret;
}
int abstractserver::RecvDate(int sockfd)
{
if(mrecvbuf == NULL || mRecvBufLen <= 0)
{
return -1;
}
bool is_read = true;
if(Checktimeout(is_read,sockfd))
{
return -1;
}
int ret = recv(sockfd,mrecvbuf,mRecvBufLen,0);
// ret <= 0 is false
// 0 close
// -1 network error
mRecvBufLen = 0;
mrecvbuf = NULL;
return ret;
}