可参考的典型的TCP client class

//.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;






}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值