// MySocket.h: 套接字封装,网络数据发送、接收
// 包 名: 套接字类
// 依 赖 组 件: ws2_32.lib,winsock2.h
//
// ------------------------------------
// * 类名:CSockAddr
// * 包 名:网络套接字
// * 功 能:封装套接字地址
// * 作 者:fusx
// * 依赖组件: winsock.h
// * 开发日期:2003/06/11
//* 修改日期:2004/06/06
// * 项目名称:
// * 版 权:
// ------------------------------------
//目的:封装套接字,可以用来向网络发送、接收数据。阻塞调用函数。
//说明:本类从《VC++6.0技术内幕》中摘录并修改
#if !defined(MY_SOCKET_H)
#define MY_SOCKET_H
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
class CSockAddr : public sockaddr_in
{
public:
//构造函数
CSockAddr()
{ sin_family = AF_INET;
sin_port = 0;
sin_addr.s_addr = 0; } // Default
CSockAddr(const SOCKADDR& sa) { memcpy(this, &sa, sizeof(SOCKADDR)); }
CSockAddr(const SOCKADDR_IN& sin) { memcpy(this, &sin, sizeof(SOCKADDR_IN)); }
//ulAddr为INADDR_ANY时默认为本机任一IP
CSockAddr(const ULONG ulAddr, const USHORT ushPort = 0) // parms are host byte ordered
{ sin_family = AF_INET;
sin_port = htons(ushPort);
sin_addr.s_addr = htonl(ulAddr); }
CSockAddr(const char* pchIP, const USHORT ushPort = 0) // dotted IP addr string
{ sin_family = AF_INET;
sin_port = htons(ushPort);
sin_addr.s_addr = inet_addr(pchIP); } // already network byte ordered
//以点的格式返回地址
LPCTSTR GetIPDottedDecimal(LPTSTR strIP = NULL,int nLen = 16)
{
if ( strIP != NULL)
memcpy(strIP,inet_ntoa(sin_addr),nLen);
return inet_ntoa(sin_addr);
}
//获取端口及地址(主机顺序)
USHORT Port() const
{ return ntohs(sin_port); }
//获取IP地址(主机顺序)
ULONG IPAddr() const
{ return ntohl(sin_addr.s_addr); }
//转换及赋值
const CSockAddr& operator=(const SOCKADDR& sa)
{ memcpy(this, &sa, sizeof(SOCKADDR));
return *this; }
const CSockAddr& operator=(const SOCKADDR_IN& sin)
{ memcpy(this, &sin, sizeof(SOCKADDR_IN));
return *this; }
operator SOCKADDR()
{ return *((LPSOCKADDR) this); }
operator LPSOCKADDR()
{ return (LPSOCKADDR) this; }
operator LPSOCKADDR_IN()
{ return (LPSOCKADDR_IN) this; }
};
//
// ------------------------------------
// * 类名:CMySocket
// * 包 名:网络套接字
// * 功 能:封装网络套接字
// * 作 者:fusx
// * 依赖组件:wsock32.lib
// * 开发日期:2003/06/11
// * 修改日期:2004/06/06
// * 版 权:sishine
// ------------------------------------
//目的:
// 封装套接字,可以用来向网络发送、接收数据。阻塞调用函数。
//说明:本类从《VC++6.0技术内幕》中摘录并修改
//
//////////////////////////////////////////////////////////////////////
typedef const struct sockaddr* LPCSOCKADDR;
class AFX_EXT_CLASS CMySocket
{
public:
CMySocket();
virtual ~CMySocket();
//参数说明:
//返回值:成功返回true,失败返回false
//char *pch为待发送或接收数据的首地址,nSize为数据大小(字节)
//int& nErrCode 为返回false时的错误代码.返回true时nErrCode无效
//LPCSOCKADDR psa为套接字地址
//int nSecs为超时设置时间,单位为秒,nMillSecs单位为微秒,当两者为0时为不考虑超时,即阻塞调用
//如果自己关闭了套接字,则返回false,nErrcode=WSAENOTSOCK
//如果超时时返回false,nErrCode = WSAETIMEDOUT;
//接收数据时,如果对方关闭连接,则返回true,且nBytesReceived = 0
public:
void operator=(SOCKET sck);
//创建套接字,成功返回真,否则假,默认创建类型为SOCK_STREAM
bool Create(int nType=SOCK_STREAM/* SOCK_STREAM or SOCK_DGRAM*/);
//绑定地址
bool Bind(LPCSOCKADDR psa);
bool Bind(LPCTSTR strIP, int nPort);
//侦听(服务器端用)
bool Listen();
//连接服务器地址
bool Connect(LPCSOCKADDR psa);
bool Connect(LPCTSTR strIP, int nPort);
//默认为阻塞操作,接受客户端连接(服务器端用),新套接字为s,客户端地址在psa中
//侦听被取消时,返回false,但nErrCode=WSAEINTR,超时时返回false,nErrCode = 0;
bool Accept(CMySocket& s, LPSOCKADDR psa,int nSecs=0);
//发送数据,nBytesSent为实际发送出去的字节数
bool Send(const char* pch, const int nSize, int& nBytesSent,int nSecs = 0);
//发送全部数据,直到所有的数据发送完毕或者出错、超时才返回
bool Write(const char* pch, const int nSize,int nSecs = 0);
//如果对方套接字被关闭,则返回true,且nBytesReceived为0字符,其余错误见上面描述
bool Receive(char* pch, const int nSize,int& nBytesReceived,int nSecs = 0);
//发送数据报,实际发送出去的数据大小为nBytesSent
bool SendDatagram( LPCSOCKADDR psa,const char* pch, const int nSize,
int& nBytesSent, int nSecs = 0);
//接收数据报,实际接收到的数据大小为nBytesReceived
bool ReceiveDatagram( LPSOCKADDR psa, char* pch, const int nSize,
int& nBytesReceived, int nSecs = 0);
//获取对方的套接字地址
bool GetPeerAddr(LPSOCKADDR psa);
//获取本地的套接字地址
bool GetSockAddr(LPSOCKADDR psa);
//根据名字获取主机地址,失败返回地址为0
static CSockAddr GetHostByName(const char* pchName, const USHORT ushPort = 0);
//根据地址获取主机名,调用者需要删除char*内存;失败返回NULL。
static const char* GetHostByAddr(LPCSOCKADDR psa);
//获取本地计算机的IP及主机名
static bool GetLocalHostInfo(LPTSTR strHostName,LPTSTR strHostIP);
//关闭套接字,并可能返回错误
bool Close();
//本套接字可以与SOCKET通用
operator SOCKET()
{ return m_hSocket; }
private:
SOCKET m_hSocket;
int m_nErrCode;
public:
//根据错误代码获取错误字符串
bool GetErrorMessage(const int nErrCode, char *pErrMsg,int nMaxLen);
inline int GetErrorCode(){return m_nErrCode;};
// 判断是否有效(非空)
inline bool IsValid(void){return m_hSocket!=INVALID_SOCKET;};
};
#endif //