您的位置:首页 > 理论基础 > 计算机网络

可参考的典型的TCP client class

2015-07-08 18:25 489 查看
//.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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: