.h文件
#pragma once
#include "xobject.h"
#include "sockdef.h"
class CXSocket : public CXObject
{
public:
SOCKET m_Socket;
long m_iTimeOut;
private:
void Init()
{
m_Socket = INVALID_SOCKET;
m_iTimeOut = DEFAULT_TIMEOUT;
}
public:
CXSocket(void);
~CXSocket(void);
public:
char* GetLocalIP(char *szIP);
int CloseSocket(bool bForce);
public:
bool operator != (CXSocket& sockfd)
{
return (sockfd.m_Socket != this->m_Socket);
}
bool operator == (CXSocket& sockfd)
{
return (sockfd.m_Socket == this->m_Socket);
}
public:
int SetTimeOut(long sec)
{
m_iTimeOut = sec;
return OK;
}
int SetNonBlock(unsigned long iNonBlock = 1)
{
unsigned long NonBlock = 1;
return 0 > IOCtlSocket(FIONBIO, &NonBlock) ? FAIL : OK;
}
int SetLinger(u_short l_onoff = 1, u_short l_linger = 0)
{
//设 SO_LINGER 设置为零(linger结构成员l_onoff不为0,但l-linger为0),
//便不担心closesocket调用进入“锁定”状态(等待完成状态。),
//即使队列中的数据尚未发送。或者尚未发出收到确认,也不担心。
//“强行关闭”,因为SOCKET 虚拟通信回路会立即重设,
//尚未发出的所有数据都会丢失。而远端,正在接受的调用都失败,同时返回
//WSAECONNRESET错误。
struct linger stSndOver;
memset(&stSndOver, 0, sizeof(struct linger));
stSndOver.l_onoff = l_onoff;
stSndOver.l_linger = l_linger;
int iLen = (int)sizeof(stSndOver);
return 0 > SetSockOpt(SOL_SOCKET, SO_LINGER, (char*)&stSndOver, iLen) ? FAIL : OK;
}
int SetReuseAddr(int iReuseAddr = 1)
{
return 0 > SetSockOpt(SOL_SOCKET, SO_REUSEADDR, (char*)&iReuseAddr, (int)sizeof(iReuseAddr)) ? FAIL : OK;
}
//SO_KEEPALIVE
//程序请求基层服务提供者在TCP连接上使用“保持活动”的数据包。
//假如由于“保持活动”造成连接的中断(很长时间没有发数据了。),
//便会向SOCKET上正在进行的任何一个调用
//返回一个WSAENETRESET错误代码。而后续的调用都会返回WSAENOTCONN错误。
//发送时间间隔2小时。
//2000 使用SIO_KEEPALIVE_VALS可以设置发送时间间隔。
int SetKeepAlive(int iAliveFlag = 1)
{
return 0 > SetSockOpt(SOL_SOCKET, SO_KEEPALIVE, (char*)&iAliveFlag, (int)sizeof(iAliveFlag)) ? FAIL : OK;
}
int SelectSend(long timeout);
int SelectRecv(long timeout);
int SelectExcept(long timeout);
protected:
int GetSockOpt(int level, int optname, char *optval, int *optlen)
{
return getsockopt (m_Socket, level,optname, optval, optlen);
}
int SetSockOpt(int level, int optname, const char *optval, int len)
{
return setsockopt(m_Socket, level, optname, optval, len);
}
int GetLastError()
{
return ::WSAGetLastError();
}
/*
返回
< 0:调用失败
== 0:超时
*/
int Select(fd_set* readset, fd_set* writeset, fd_set* exceptset, long timeout)
{
timeout = timeout <= 0 ? m_iTimeOut : timeout;
struct timeval stTimeOut;
stTimeOut.tv_sec = timeout;
stTimeOut.tv_usec = 0;
return select(m_Socket, readset, writeset, exceptset, &stTimeOut);
}
int IOCtlSocket(long cmd, u_long *argp)
{
return ioctlsocket(m_Socket, cmd, argp)
}
int CreateSocket();
bool IsVaildSocket();
protected:
void InitSockAddr(struct sockaddr_in &internetAddr, const char* szIP, unsigned int iport);
int Bind(sockaddr_in &sockAddr_in);
};
.cpp文件:
#include "StdAfx.h"
#include "XSocket.h"
CXSocket::CXSocket(void)
{
Init();
}
CXSocket::~CXSocket(void)
{
CloseSocket();
}
int CXSocket::CloseSocket(bool bForce)
{
if (!IsVaildSocket())
{
return SEL_FAIL;
}
if(bForce)
{
//强行关闭[主机强迫关闭],WSAECONNRESET
SetLinger();
}
closesocket(m_Socket);
m_Socket = INVALID_SOCKET;
return OK;
}
char* CXSocket::GetLocalIP(char *szIP)
{
char szhostname[512+1] = {0};
char *pIP = NULL;
hostent* phostent;
::gethostname(szhostname, sizeof(szhostname) - 1);
phostent = gethostbyname(szhostname);
if (NULL != phostent->h_addr_list)
{
in_addr addr;
memset((void*)&addr, 0, sizeof(in_addr));
memcpy((void*)&addr, phostent->h_addr_list[0], 4);
pIP = inet_ntoa(addr);
strncpy(szIP, pIP, strlen(pIP));
}
return szIP;
}
int CXSocket::SelectRecv(long timeout)
{
if (!IsVaildSocket())
{
return SEL_FAIL;
}
fd_set freadset;
memset(&freadset, 0, sizeof(struct fd_set));
FD_CLR(m_Socket, &freadset);
FD_SET(m_Socket, &freadset);
return Select(&freadset, NULL, NULL, timeout);
}
int CXSocket::SelectSend(long timeout)
{
if (!IsVaildSocket())
{
return SEL_FAIL;
}
fd_set writeset;
memset(&writeset, 0, sizeof(struct fd_set));
FD_CLR(m_Socket, &writeset);
FD_SET(m_Socket, &writeset);
return Select(NULL, &writeset, NULL, timeout);
}
int CXSocket::SelectExcept(long timeout)
{
if (!IsVaildSocket())
{
return SEL_FAIL;
}
fd_set except;
memset(&except, 0, sizeof(struct fd_set));
FD_CLR(m_Socket, &except);
FD_SET(m_Socket, &except);
return Select(NULL, NULL, &except, timeout);
}
int CXSocket::CreateSocket()
{
m_Socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if (!IsVaildSocket())
{
return FAIL;
}
return OK;
}
bool CXSocket::IsVaildSocket()
{
return (m_Socket != INVALID_SOCKET);
}
void CXSocket::InitSockAddr(struct sockaddr_in &stInternetAddr, const char* szIP, unsigned int iPort)
{
memset(&stInternetAddr, 0, sizeof(stInternetAddr));
stInternetAddr.sin_family = AF_INET;
if(NULL == szIP || "/0" == szIP[0])
{
stInternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
}
else
{
stInternetAddr.sin_addr.s_addr = (unsigned int)inet_addr(szIP);
}
stInternetAddr.sin_port = htons(iPort);
}
int CXSocket::Bind(struct sockaddr_in &stSockAddr_in)
{
return bind(m_Socket, (const struct sockaddr)&stSockAddr_in, sizeof(stSockAddr_in));
}