//.h
#pragma once
#include <WINSOCK2.H>
#define TCP 0
#define UDP 1
//using namespace std
using std::string;
class abstractclient
{
public:
SOCKET msockfd;
int mserverport;
int mtimeout;
int mtransmode;
char *mserverip;
char *mhostname;//域名
char *mclientip;
char *msendbuf;
char *mrecvbuf;
int mNeedSend;//要发送的数据
int mRecvBufLen;//接受缓冲区大小
public:
abstractclient(int port, char *serip, char *hostname,int t_mode);
virtual ~abstractclient(void);
bool init_socket();
void Close();
void SetBlock(bool bblock);
bool Checktimeout(bool isread);
bool ConnectServer(void);
int SendData(void);
int RecvDate(void);
//virtual bool SendCommand(const char* szMessage)=0;
};
//.cpp
#include "StdAfx.h"
#include "abstractclient.h"
abstractclient::abstractclient(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);
}
}
}
abstractclient::~abstractclient(void)
{
if(mserverip!=NULL)
{
free((void *)mserverip);
}
if(mhostname!=NULL)
{
free((void *)mhostname);
}
Close();
printf("release abstractclient !\n");
}
void abstractclient::Close()
{
#ifdef Linux
if(msockfd >= 0)
{
shutdown(msockfd,SHUT_WR);
close(msockfd);
}
#elif _WIN32_WINNT
if(msockfd >= 0)
{
shutdown(msockfd,SD_SEND);
closesocket(msockfd);
}
#endif
msockfd = -1;
}
//设置网络套接字阻塞或者非阻塞
void abstractclient::SetBlock(bool bblock)
{
#ifdef Linux
int mode = bblock ? 0 : 1;
ioctl(msockfd, FIONBIO, &mode); //设置为非阻塞模式
#elif _WIN32_WINNT
unsigned long op = bblock ? 0 : 1;
if (ioctlsocket(msockfd, FIONBIO, &op) == SOCKET_ERROR)
{
printf("Unable to Set Blocking");
}
#endif
}
//判断网络是否超时
bool abstractclient::Checktimeout(bool isread)
{
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(msockfd, &readset);
fdset = &readset;
}
else
{
FD_SET(msockfd, &writeset);
fdset = &writeset;
}
/* 等待连接,如果超时(10s),那么返回连接错误 by wangjidong*/
if (select(msockfd + 1,&readset,&writeset, NULL, &tm) > 0)
{
if(FD_ISSET(msockfd,fdset))
{
return false;
}
else
{
return true;
}
}
else
{
return true;
}
return false;
}
// 初始化socket
bool abstractclient::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;
}
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));
return true;
}
// try connect server ,first init sock, then connect server
bool abstractclient::ConnectServer(void)
{
if(init_socket()==false)
{
return false;
}
sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(mserverport);
if(mhostname != NULL)
{
HOSTENT *host_entry = gethostbyname(mhostname);
mserverip = inet_ntoa(*((struct in_addr *)host_entry->h_addr)) ;
}
SetBlock(false); //设置为非阻塞模式
if ((serv_addr.sin_addr.S_un.S_addr = inet_addr(mserverip)) == INADDR_NONE)
{
Close();
return false;
}
// udp 使用connect 不需要进行三次握手,后面可以使用send 和 recv 函数
/*
方法一:
socket----->sendto()或recvfrom()
方法二:
socket----->connect()----->send()或recv()
*/
if(connect(msockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))== -1)
{
/* 表示内核连接已经建立启动,但是尚未完成 add by */
#ifdef Linux
if (errno != EINPROGRESS && errno != EWOULDBLOCK)
{
Close();
return false;
}
#endif
bool isread = false;
if(Checktimeout(isread) == true)
{
Close();
return false;
}
}
/*设置socket 阻塞模式发送接收数据*/
//阻塞模式http 协议数据够用
SetBlock(true);
return true;
}
int abstractclient::SendData()
{
if(msendbuf == NULL || mNeedSend <= 0)
{
return -1;
}
bool is_read = false;
if(Checktimeout(is_read))
{
return -1;
}
int ret = send(msockfd,msendbuf,mNeedSend,0);
// ret <= 0 is false
mNeedSend = 0;
msendbuf = NULL;
return ret;
}
int abstractclient::RecvDate()
{
if(mrecvbuf == NULL || mRecvBufLen <= 0)
{
return -1;
}
bool is_read = true;
if(Checktimeout(is_read))
{
return -1;
}
int ret = recv(msockfd,mrecvbuf,mRecvBufLen,0);
// ret <= 0 is false
// 0 close
// -1 network error
mRecvBufLen = 0;
mrecvbuf = NULL;
return ret;
}