跨平台Socket封装——对IPv4地址的封装

IPv4地址的封装主要是对sockadr_in的封装, 这是别人写的一个跨平台的代码,觉得不错,故记录下来。如果您看到代码,觉得还有改进的地方,可以说出来分享一下。
头文件SocketAddress.h

namespace LinWin
{
#define NET_DEFAULT_IP "0.0.0.0"
class CSocketAddress
{
private:
sockaddr_in m_addr;
public:
CSocketAddress(const char *ip = NET_DEFAULT_IP, unsigned short port = 0);
CSocketAddress(const sockaddr_in &addr);
CSocketAddress(const CSocketAddress &addr);
CSocketAddress& operator=(const CSocketAddress &addr);
virtual ~CSocketAddress();
public:
inline const struct sockaddr_in* GetAddress() const
{   return &m_addr; }

//添加一个非const版本的GetAddress函数
inline struct sockaddr_in* GetAddress()
{   return &m_addr; }

inline void SetAddress(const struct sockaddr_in addr)
{   m_addr = addr;  }

inline unsigned int AddressLength() const
{   return sizeof(struct sockaddr_in);  }

inline int GetFamily() const
{   return m_addr.sin_family;   }

inline void SetFamily(int fam)
{   m_addr.sin_family = fam;    }

virtual unsigned int GetHost() const
{   return m_addr.sin_addr.s_addr;  }

inline void SetHost(unsigned int addr)
{   m_addr.sin_addr.s_addr = addr;  }

inline unsigned short GetPort() const
{   return m_addr.sin_port; }

inline void SetPort(unsigned short p)
{   m_addr.sin_port = p;    }

virtual int Parse(const std::string& addrStr);
virtual int Parse(const std::string& addr, int port);
virtual std::string ToString() const;
};
}

实现文件SocketAddress.cpp

LinWin::CSocketAddress::CSocketAddress(const char *ip, unsigned short port)
{
    memset(&m_addr, 0, sizeof(sockaddr_in));
    m_addr.sin_family = AF_INET;
    m_addr.sin_addr.s_addr = inet_addr(ip);
    m_addr.sin_port = htons(port);
}

LinWin::CSocketAddress::CSocketAddress(const struct sockaddr_in& addr) : m_addr(addr)
{}

LinWin::CSocketAddress::CSocketAddress(const CSocketAddress& addr) : m_addr(addr.m_addr)
{}

LinWin::CSocketAddress::~CSocketAddress()
{}

LinWin::CSocketAddress& LinWin::CSocketAddress::operator=(const CSocketAddress& addr)
{
    if (&addr != this)
    {
        m_addr = addr.m_addr;
    }
    return *this;
}

std::string LinWin::CSocketAddress::ToString() const
{
    unsigned short port = ntohs(m_addr.sin_port);
    std::string result = inet_ntoa(m_addr.sin_addr);
    char buf[8];
    sprintf(buf, ":%d", port);
    result += buf;

    return result;
}

int LinWin::CSocketAddress::Parse(const std::string& addrStr)
{
    size_t i;
    unsigned short port = 0;
    size_t index = addrStr.find(":");
    if (index == std::string::npos || (index + 1) == addrStr.length())
        return -1;

    const char* pData = addrStr.c_str();
    i = 0;
    while (isspace(pData[i]))
        i++;
    std::string tmp;
    while (!isspace(pData[i]) && i < index)
    {
        tmp.push_back(pData[i]);
        i++;
    }
    struct hostent *hostip = ::gethostbyname(tmp.c_str());
    if (hostip == NULL)
        return -1;

    i = index + 1;
    while (!isdigit(pData[i]) && i < addrStr.length())
        i++;
    port = atoi(pData + i);

    memset(&m_addr, 0, sizeof(const struct sockaddr_in));
    m_addr.sin_family = AF_INET;
    memcpy((char*)&m_addr.sin_addr, hostip->h_addr, hostip->h_length);
    m_addr.sin_port = htons(port);

    return 0;
}

int LinWin::CSocketAddress::Parse(const std::string& addr, int port)
{
    struct hostent *hostip = ::gethostbyname(addr.c_str());
    if (hostip == NULL)
        return -1;
    memset(&m_addr, 0, sizeof(const struct sockaddr_in));
    m_addr.sin_family = AF_INET;
    memcpy((char*)&m_addr.sin_addr, hostip->h_addr, hostip->h_length);
    m_addr.sin_port = htons(port);

    return 0;
}

命名空间是我自己添加的,如果不需要可以去掉。整体的代码是比较简单的,就是类的基础知识和socketaddr_in结构体的使用。类中留有两个接口,一个是解析像这样”域名 + 端口号”(如”www.baidu.com:80”)形式的接口;一个是输出”IP + 端口”(如”192.168.0.1:80”)这样的形式的接口。想要修改这两个接口,可以直接继承,在子类中重写这个接口。
新增一个接口,是把“域名”和“端口号”作为两个参数传入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值