.h文件
#pragma once
#include "xsocket.h"
#define SOCKET_IO_FLAG 0
class CClientSocket :
public CXSocket
{
public:
SOCKADDR_IN m_stClientSockAddr;
char m_szClientIP[IP_LEN];
int m_iClientPort;
public:
CClientSocket(void);
virtual ~CClientSocket(void);
public:
/*
iSend 为每次发送字节数
iTotal 为需要发送的字节数
*/
int Send(char* pPack, int iSend, int iTotal, int iFlag = SOCKET_IO_FLAG);
int Recv(char* pPack, int iRecv, int iTotal, int iFlag = SOCKET_IO_FLAG);
int Connect(char* pRemoteIP, unsigned int iRemotePort, unsigned int iLocalPort = 0);
char* GetClientSockAddrInfo();
char* GetClientIP()
{
return GetClientSockAddrInfo();
}
protected:
/*
iLen 为每次接受字节数
*/
int Recv(char* pPack, int iLen, int iFlag = SOCKET_IO_FLAG);
/*
iLen 为每次发送字节数
*/
int Send(char* pPack, int iLen, int iFlag = SOCKET_IO_FLAG);
int Connect(const struct sockaddr_in* name, int namelen);
};
.CPP文件
#include "StdAfx.h"
#include "clientsocket.h"
CClientSocket::CClientSocket(void)
{
memset(m_stClientSockAddr, 0, sizeof(SOCKADDR_IN));
memset(m_szClientIP, 0, sizeof(m_szClientIP) - 1);
m_iClientPort = 0;
}
CClientSocket::~CClientSocket(void)
{
}
int CClientSocket::Recv(char* sPack, int iLen, int iFlag)
{
return ::recv(m_Socket, sPack, iLen, iFlag);
}
int CClientSocket::Recv(char* sPack, int iRecv, int iTotalLen, int iFlag)
{
int err = 0;
int iTotal = 0;//累计已经发送(接受)的数据
int iLeave = iTotalLen; //剩余数据长度
while(1)
{
if((err = SelectRecv()) < 0)
{
return FAIL;
}
else if (SEL_TIMEOUT == err)
{
//超时
return SEL_TIMEOUT;
}
if((err = Recv(sPack + iTotal, iRecv, iFlag)) <= 0)
{
break;
}
//累计"接收数据"
iTotal += err;
iLeave = iTotalLen - iTotal; //剩余数据长度 = 需要发送(接受)的数据 - 已经发送(接受)的数据
if(iLeave < iRecv)
{
iRecv = iLeave;
}
else if(iLeave <= 0)
{
//"累计已经发送(接受)的数据"大于"需要发送(接受)的数据",提示错误
if(iTotal > iTotalLen)
{
Err("接受数据内存溢出:累计已经接受的数据大于需要接受的数据.");
}
break;
}
}
//返回"累计已经接受的数据"
return iTotal;
}
int CClientSocket::Send(char* sPack, int iLen, int iFlag)
{
return ::send(m_Socket, sPack, iLen, iFlag);
}
int CClientSocket::Send(char* sPack, int iSend, int iTotalLen, int iFlag)
{
int err = 0;
int iTotal = 0;//累计已经发送(接受)的数据
int iLeave = iTotalLen; //剩余数据长度
while(1)
{
if((err = SelectSend()) < 0)
{
return FAIL;
}
else if (SEL_TIMEOUT == err)
{
// 超时
return SEL_TIMEOUT;
}
if((err = Send(sPack + iTotal, iSend, iFlag)) <= 0)
{
break;
}
//累计"发送数据"
iTotal += err;
iLeave = iTotalLen - iTotal; //剩余数据长度 = 需要发送(接受)的数据 - 已经发送(接受)的数据
if(iLeave < iSend)
{
iSend = iLeave;
}
else if(iLeave <= 0)
{
//"累计已经发送(接受)的数据"大于"需要发送(接受)的数据",提示错误
if(iTotal > iTotalLen)
{
Err("发送数据内存溢出:累计已经发送的数据大于需要发送的数据.");
}
break;
}
}
//返回"累计已经发送的数据"
return iTotal;
}
int CClientSocket::Connect(const struct sockaddr_in* internetRemoteAddr, int namelen)
{
return SOCKET_ERROR == connect(m_Socket, (struct sockaddr*)internetRemoteAddr, namelen) ? FAIL : OK;
}
int CClientSocket::Connect(char* szRemoteIP, unsigned int iRemotePort, unsigned int iLocalPort)
{
if(iRemotePort <= 0)
{
return FAIL;
}
//创建SOCKET失败,返回
if(FAIL == CreateSocket())
{
Err("CClientSocket::Connect-CreateSocket 失败[%d]", GetLastError());
return FAIL;
}
SetNonBlock();
SetReuseAddr();
SetKeepAlive();
//iret = SetLinger();
if (iLocalPort > 0)
{
//char szLocalIP[IP_LEN+1] = {0};
struct sockaddr_in stLocalSockAddr;
//InitSockAddr(stLocalSockAddr, GetLocalIP(szLocalIP), iLocalPort);
InitSockAddr(stLocalSockAddr, NULL, iLocalPort);
if (FAIL == Bind(stLocalSockAddr))
{
Err("CClientSocket::Connect-Bind 本地地址失败[%d]", GetLastError());
return FAIL;
}
}
struct sockaddr_in stInternetRemoteAddr;
InitSockAddr(stInternetRemoteAddr, szRemoteIP, iRemotePort);
//说明:
//如果 TCPGetLastErr () != WSAEWOULDBLOCK
//那么是真的连接失败了。比如端口错误产生的10061就是真的连接有问题。
//如果等于WSAEWOULDBLOCK,那么就要开始
//连接等待了。
//连接等待一定时间返回后有又如下几种
//0,连接超时,决定是否需要在等待。
//1,连接成功(即使当前SOCKET可度),
//-1,select调用失败,具体分析要看失败的ERROR。
if(SOCKET_ERROR == Connect(&stInternetRemoteAddr, (int)sizeof(stInternetRemoteAddr)))
{
Err("CClientSocket::Connect-Connect 失败[%d]", GetLastError());
return FAIL;
}
return OK;
}
char* CClientSocket::GetClientSockAddrInfo()
{
struct in_addr& stIn_Addr = m_stClientSockAddr.sin_addr;
char *pIP = inet_ntoa(stIn_Addr);
m_iClientPort = htons(m_stClientSockAddr.sin_port);
memset(m_szClientIP, 0, sizeof(m_szClientIP) - 1);
strncpy(m_szClientIP, pIP, strlen(pIP));
return m_szClientIP;
}