Address模块概述
socket
的通信都需要与地址打交道,所以封装了Address
模块,不用进行繁琐的一系列操作。
Address
模块有主要一下几类:
- class Address:基类,抽象类,对应
sockaddr
类型。提供获取地址的方法,以及一些基础操作的纯虚函数。 - class IPAddress:继承
Address
,抽象类。提供关于IP
操作的纯虚函数。 - class IPv4Address:继承
IPAddress
,对应sockaddr_in
类型。一个IPv4
地址。 - class IPv6Address:继承
IPAddress
,对应sockaddr_in6
类型。一个IPv6
地址。 - class UinxAddress:继承
Address
,Unix
域套接字类,对应sockaddr_un
类型。一个Unix
地址。 - class UnknowAddress:继承
Address
,对应sockaddr
类型。未知地址。
socket地址结构体
sockaddr
和sockaddr_in
都为16字节,sockaddr_in6
为28字节。
如果要问为什么字节数不同还能相互转化,那是因为在进行类型转换时,只需要将指针类型进行转换即可,不需要改变结构体的大小。
/* Structure describing a generic socket address. */
struct sockaddr
{
uint16 sa_family; /* Common data: address family and length. */
char sa_data[14]; /* Address data. */
};
/* Structure describing an Internet socket address. */
struct sockaddr_in
{
uint16 sin_family; /* Address family AF_INET */
uint16 sin_port; /* Port number. */
uint32 sin_addr.s_addr; /* Internet address. */
unsigned char sin_zero[8]; /* Pad to size of `struct sockaddr'. */
};
/* Ditto, for IPv6. */
struct sockaddr_in6
{
uint16 sin6_family; /* Address family AF_INET6 */
uint16 sin6_port; /* Transport layer port # */
uint32 sin6_flowinfo; /* IPv6 flow information */
uint8 sin6_addr[16]; /* IPv6 address */
uint32 sin6_scope_id; /* IPv6 scope-id */
};
struct in6_addr
{
union
{
uint8_t __u6_addr8[16];
uint16_t __u6_addr16[8];
uint32_t __u6_addr32[4];
} __in6_u;
#define s6_addr __in6_u.__u6_addr8
#ifdef __USE_MISC
# define s6_addr16 __in6_u.__u6_addr16
# define s6_addr32 __in6_u.__u6_addr32
#endif
};
#endif /*
getaddrinfo
函数将主机名、主机地址、服务名和端口的字符串表示转换成套接字地址结构体,应用程序只要处理由getaddrinfo函数填写的套接口地址结构。
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int getaddrinfo( const char *node,
const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
1)nodename:节点名可以是主机名,也可以是数字地址。(IPV4的10进点分,或是IPV6的16进制);
2)servname:包含十进制数的端口号或服务名如(ftp,http);
3)hints:是一个空指针或指向一个addrinfo结构的指针,由调用者填写关于它所想返回的信息类型的线索;
4)res:存放返回addrinfo结构链表的指针;
/* 释放addrinfo指针 */
void freeaddrinfo(struct addrinfo *res);
/* getaddrinfo函数返回的错误码转换为对应的错误信息字符串 */
const char *gai_strerror(int errcode);
struct addrinfo {
int ai_flags; // 位掩码,修改默认行为
int ai_family; // socket()的第一个参数
int ai_socktype; // socket()的第二个参数
int ai_protocol; // socket()的第三个参数
socklen_t ai_addrlen; // sizeof(ai_addr)
struct sockaddr *ai_addr; // sockaddr指针
char *ai_canonname; // 主机的规范名字
struct addrinfo *ai_next; // 链表的下一个结点
}
参数说明:
ai_flags:
1)AI_ADDRCONFIG: 只有当本地主机被配置为IPv4时,getaddrinfo返回IPv4地址,IPv6同理。
2)AI_CANONNAME: ai_canonname默认为NULL,设置此标志位,告诉getaddrinfo将列表中第一个addrinfo结构体的ai_cannoname字段指向host的权威(官方)名字。
3)AI_NUMERICSERV: service默认为服务名或端口号。这个标志强制参数service为端口号。
4)AI_PASSIVE: getaddrinfo默认返回套接字地址,客户端可以在调用connect时用作主动套接字。此标志位告诉该函数,返回的套接字地址可能被服务器用作监听套接字。此时,host应该为NULL。
5)AI_NUMERICHOST:用于指示getaddrinfo函数在解析主机名时是否进行名称解析。当我们需要使用IP地址而不是主机名来创建套接字时,可以将AI_NUMERICHOST常量作为getaddrinfo函数的hints参数中的ai_flags成员的值,以指示getaddrinfo函数不进行主机名解析,而直接使用传入的IP地址。这样可以避免主机名解析带来的延迟和不确定性,提高套接字的创建效率和可靠性。
getifaddrs
函数用于获取系统中所有网络接口的信息。
#include <sys/types.h>
#include <ifaddrs.h>
/* getifaddrs创建一个链表,链表上的每个节点都是一个struct ifaddrs结构,getifaddrs()返回链表第一个元素的指针。
* 成功返回0, 失败返回-1,同时errno会被赋允相应错误码。 */
int getifaddrs(struct ifaddrs **ifap);
/* 释放ifaddrs */
void freeifaddrs(struct ifaddrs *ifa);
struct ifaddrs {
struct ifaddrs *ifa_next; /* 指向链表中下一个struct ifaddr结构 */
char *ifa_name; /* 网络接口名 */
unsigned int ifa_flags; /* 网络接口标志 */
struct sockaddr *ifa_addr; /* 指向一个包含网络地址的sockaddr结构 */
struct sockaddr *ifa_netmask; /* 指向一个包含网络掩码的结构 */
union {
struct sockaddr *ifu_broadaddr;
/* 如果(ifa_flags&IFF_BROADCAST)有效,ifu_broadaddr指向一个包含广播地址的结构 */
struct sockaddr *ifu_dstaddr;
/* 如果(ifa_flags&IFF_POINTOPOINT)有效,ifu_dstaddr指向一个包含p2p目的地址的结构 */
} ifa_ifu;
#define ifa_broadaddr ifa_ifu.ifu_broadaddr
#define ifa_dstaddr ifa_ifu.ifu_dstaddr
void *ifa_data; /* 指向一个缓冲区,其中包含地址族私有数据。没有私有数据则为NULL */
};
详解
根据前缀长度创建掩码
/*
* sizeof(T) * 8: 算出有多少位
* sizeof(T) * 8 - bits: 算出掩码0的个数
* 1 <<: 将 1 左移0的个数位
* -1: 前bits位数置为0,后面的 sizeof(T) * 8 - bits 位都为1
* ~: 将前bits位置为1,后面全部置为0
*/
template<class T>
static T CreateMask(uint32_t bits) {
return ~((1 << (sizeof(T) * 8 - bits)) - 1);
}
根据掩码计算前缀长度
template<class T>
static uint32_t CountBytes(T value) {
uint32_t result = 0;
for (; value; ++result) {
// 将最右边的1置为0
value &= value - 1;
}
return result;
}
class Address
提供三个纯虚函数
// 获得sockaddr指针
virtual const sockaddr* getAddr() const = 0;
// 获得sockaddr长度
virtual socklen_t getAddrLen() const = 0;
// 可读性输出地址
virtual std::ostream& insert(std::ostream& os) const = 0;
Create(通过sockaddr创建地址)
静态方法
Address::ptr Address::Create(const sockaddr* sockaddr, socklen_t addrlen) {
if (sockaddr == nullptr) {
return nullptr;
}
Address::ptr result;
switch (sockaddr->sa_family) {
case AF_INET:
result.reset(new IPv4Address(*(const sockaddr_in*)sockaddr));
break;
case AF_INET6:
result.reset(new IPv6Address(*(const sockaddr_in6*)sockaddr));
break;
default:
result.reset(new UnknowAddress(*sockaddr));
break;
}
return result;
}
Lookup(通过host地址返回所有Address)
静态方法
bool Address::Lookup(std::vector<Address::ptr>& result, const std::string& host,
int family, int type, int protocol) {
addrinfo hints, * results, * next;
hints.ai_addr = NULL;
hints.ai_addrlen = 0;
hints.ai_canonname = NULL;
hints.ai_family = family;
hints.ai_flags = 0;
hints.ai_next = NULL;
hints.ai_protocol = protocol;
hints.ai_socktype = type;
std::string node;
const char* service = nullptr;
// host = www.baidu.com:http
// 检查 ipv6address service [address]:
if (!host.empty() && host[0] == '[') {
// 查找第一个 ] 的位置,返回该指针
const char* endipv6 = (const char*)memchr(host.c_str() + 1, ']', host.size() - 1);
// 找到了 ]
if (endipv6) {
// 是否为 :
if (*(endipv6 + 1) == ':') {
// endipv6后两个字节为端口号
service = endipv6 + 2;
}
// 地址为[]里的内容
node = host.substr(1, endipv6 - host.c_str() - 1);
}
}
// ipv4 ip:port
if (node.empty()) {
// 找到第一个:
service = (const char*)memchr(host.c_str(), ':', host.size());
// 找到了
if (service) {
// 后面没有 : 了
if (!memchr(service + 1, ':', host.c_str() + host.size() - service - 1)) {
// 拿到地址
node = host.substr(0, service - host.c_str());
// :后面就是端口号
++service;
}
}
}
// 如果没设置端口号,就将host赋给他
if (node.empty()) {
node = host;
}
// 获得地址链表
int error = getaddrinfo(node.c_str(), service, &hints, &results);
if (error) {
SYLAR_LOG_ERROR(g_logger) << "Address::Lookup getaddress(" << host
<< ", " << family << ", " << type << ") error = " << error
<< ", gai_strerror = " << gai_strerror(error);
return false;
}
// results指向头节点,用next遍历
next = results;
while (next) {
// 将得到的地址创建出来放到result容器中
result.push_back(Create(next->ai_addr, next->ai_addrlen));
next = next->ai_next;
}
// 释放addrinfo指针
freeaddrinfo(results);
return true;
}
LookupAny(通过host返回任意Address)
静态方法
Address::ptr Address::LookupAny(const std::string& host, int family,
int type, int protocol) {
std::vector<Address::ptr> result;
if (Lookup(result, host, family, type, protocol)) {
return result[0];
}
return nullptr;
}
LookupAnyIPAddress(通过host返回任意IPAddress)
静态方法
std::shared_ptr<IPAddress> Address::LookupAnyIPAddress(const std::string& host, int family,
int type, int protocol) {
std::vector<Address::ptr> result;
if (Lookup(result, host, family, type, protocol)) {
for (auto& i : result) {
IPAddress::ptr v = std::dynamic_pointer_cast<IPAddress>(i);
if (v) {
return v;
}
}
}
return nullptr;
}
GetInterfaceAddresses(返回本机所有网卡的<网卡名, 地址, 子网掩码位数>)
静态方法
bool Address::GetInterfaceAddresses(std::multimap<std::string,
std::pair<Address::ptr, uint32_t> >& result, int family) {
struct ifaddrs* next, * results;
if (getifaddrs(&results) != 0) {
SYLAR_LOG_ERROR(g_logger) << "Address::GetInterfaceAddress getifaddrs "
<< "errno = " << errno << ", strerrno = " << strerror(errno);
return false;
}
try {
// results指向头节点,用next遍历
for (next = results; next; next = next->ifa_next) {
Address::ptr addr;
uint32_t prefix_length = ~0u;
// 地址族确定 并且 该地址族与解析出来的不同
if (family != AF_UNSPEC && family != next->ifa_addr->sa_family) {
continue;
}
switch (next->ifa_addr->sa_family) {
// IPv4
case AF_INET:
{
// 创建ipv4地址
addr = Create(next->ifa_addr, sizeof(sockaddr_in));
// 掩码地址
uint32_t netmask = ((sockaddr_in*)next->ifa_netmask)->sin_addr.s_addr;
// 前缀长度,网络地址的长度
prefix_length = CountBytes(netmask);
}
break;
// IPv6
case AF_INET6:
{
// 创建ipv6地址
addr = Create(next->ifa_addr, sizeof(sockaddr_in6));
// 掩码地址
in6_addr& netmask = ((sockaddr_in6*)next->ifa_netmask)->sin6_addr;
prefix_length = 0;
// 前缀长度,16字节挨个算
for (int i = 0; i < 16; ++i) {
prefix_length += CountBytes(netmask.__in6_u.__u6_addr8[i]);
}
}
break;
default:
break;
}
// 插入到容器中,保存了网卡名,地址和前缀长度
if (addr) {
result.insert(std::make_pair(next->ifa_name, std::make_pair(addr, prefix_length)));
}
}
}
catch (...) {
SYLAR_LOG_ERROR(g_logger) << "Address::GetInterfaceAddresses exception";
freeifaddrs(results);
return false;
}
// 释放results
freeifaddrs(results);
return true;
}
GetInterfaceAddresses(获取指定网卡的地址和子网掩码位数)
bool Address::GetInterfaceAddresses(std::vector<std::pair<Address::ptr, uint32_t> >& result,
const std::string& iface, int family) {
if (iface.empty() || iface == "*") {
// 创建监听任意IP地址的连接请求的ipv4
if (family == AF_INET || family == AF_UNSPEC) {
result.push_back(std::make_pair(Address::ptr(new IPv4Address()), 0u));
}
// 创建监听任意IP地址的连接请求的ipv6
if (family == AF_INET6 || family == AF_UNSPEC) {
result.push_back(std::make_pair(Address::ptr(new IPv6Address()), 0u));
}
return true;
}
std::multimap<std::string, std::pair<Address::ptr, uint32_t> >results;
// 获取失败
if (!GetInterfaceAddresses(results, family)) {
return false;
}
// 返回pair,first为第一个等于的迭代器,second为第一个大于的迭代器
auto its = results.equal_range(iface);
// 将first与second之间的全部拿出来
for (; its.first != its.second; ++its.first) {
result.push_back(its.first->second);
}
return true;
}
getFamily(返回协议簇)
int Address::getFamily() const {
return getAddr()->sa_family;
}
toString(返回可读性字符串)
std::string Address::toString() const {
std::stringstream ss;
insert(ss);
return ss.str();
}
class IPAddress
提供5个纯虚函数
// 获得广播地址
virtual IPAddress::ptr broadcastAddress(uint32_t prefix_len) = 0;
// 获得网络地址
virtual IPAddress::ptr networkAddress(uint32_t prefix_len) = 0;
// 获得子网掩码地址
virtual IPAddress::ptr subnetMask(uint32_t prefix_len) = 0;
// 获得端口号
virtual uint16_t getPort() const = 0;
// 设置端口号
virtual void setPort(uint16_t v) = 0;
Create(通过IP、域名、服务器名,端口号创建IPAddress)
静态方法
IPAddress::ptr IPAddress::Create(const char* address, uint16_t port) {
addrinfo hints;
addrinfo* results;
memset(&hints, 0, sizeof(hints));
// 协议无关
hints.ai_family = AF_UNSPEC;
int error = getaddrinfo(address, "http", &hints, &results);
if (error) {
SYLAR_LOG_ERROR(g_logger) << "IPAddress::Create(" << address
<< ", " << port << ") error = " << error
<< ", gai_strerror = " << gai_strerror(error);
return nullptr;
}
try {
IPAddress::ptr result = std::dynamic_pointer_cast<IPAddress>(
Address::Create(results->ai_addr, (socklen_t)results->ai_addrlen)
);
if (result) {
result->setPort(port);
}
freeaddrinfo(results);
return result;
} catch (...) {
freeaddrinfo(results);
return nullptr;
}
}
class IPv4Address
mumber(成员变量)
// sockaddr_in 结构体
sockaddr_in m_addr;
Create(通过IP,端口号创建IPv4Address)
静态方法
IPv4Address::ptr IPv4Address::Create(const char* address, uint16_t port) {
IPv4Address::ptr rt(new IPv4Address);
rt->m_addr.sin_port = byteswapOnLittleEndian(port);
// 将一个IP地址的字符串表示转换为网络字节序的二进制形式
int result = inet_pton(AF_INET, address, &rt->m_addr.sin_addr.s_addr);
if (result <= 0) {
SYLAR_LOG_ERROR(g_logger) << "IPv4Address::Create(" << address << ", "
<< port << ") rt = " << result << " errno = " << errno
<< " strerror = " << strerror(errno);
return nullptr;
}
return rt;
}
IPv4Address(构造函数)
// 通过sockaddr_in
IPv4Address::IPv4Address(const sockaddr_in& sockaddr) {
m_addr = sockaddr;
}
// 通过ip地址和端口号
IPv4Address::IPv4Address(uint32_t address, uint16_t port) {
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sin_family = AF_INET;
m_addr.sin_port = byteswapOnLittleEndian(port);
m_addr.sin_addr.s_addr = byteswapOnLittleEndian(address);
}
getAddr(返回sockaddr指针)
const sockaddr* IPv4Address::getAddr() const {
return (sockaddr*)&m_addr;
}
getAddrLen(返回sockaddr的长度)
socklen_t IPv4Address::getAddrLen() const {
return sizeof(m_addr);
}
insert(可读性输出地址)
std::ostream& IPv4Address::insert(std::ostream& os) const {
uint32_t addr = byteswapOnLittleEndian(m_addr.sin_addr.s_addr);
os << ((addr >> 24) & 0xff) << "."
<< ((addr >> 16) & 0xff) << "."
<< ((addr >> 8) & 0xff) << "."
<< (addr & 0xff);
os << ": " << byteswapOnLittleEndian(m_addr.sin_port);
return os;
}
broadcastAddress(返回广播地址)
IPAddress::ptr IPv4Address::broadcastAddress(uint32_t prefix_len) {
if (prefix_len > 32) {
return nullptr;
}
sockaddr_in baddr(m_addr);
// 主机号全为1
baddr.sin_addr.s_addr |= ~byteswapOnLittleEndian(
CreateMask<uint32_t>(prefix_len));
return IPv4Address::ptr(new IPv4Address(baddr));
}
networkAddress(返回网络地址)
IPAddress::ptr IPv4Address::networkAddress(uint32_t prefix_len) {
if (prefix_len > 32) {
return nullptr;
}
sockaddr_in naddr(m_addr);
// 主机号全为0
naddr.sin_addr.s_addr &= byteswapOnLittleEndian(
CreateMask<uint32_t>(prefix_len));
return IPv4Address::ptr(new IPv4Address(naddr));
}
subnetMask(返回子网掩码地址)
IPAddress::ptr IPv4Address::subnetMask(uint32_t prefix_len) {
sockaddr_in subnet;
memset(&subnet, 0, sizeof(subnet));
subnet.sin_family = AF_INET;
// 根据前缀长度获得子网掩码
subnet.sin_addr.s_addr = byteswapOnLittleEndian(CreateMask<uint32_t>(prefix_len));
return IPv4Address::ptr(new IPv4Address(subnet));
}
getPort(返回端口号)
uint16_t IPv4Address::getPort() const {
return byteswapOnLittleEndian(m_addr.sin_port);
}
setPort(设置端口号)
void IPv4Address::setPort(uint16_t v) {
m_addr.sin_port = byteswapOnLittleEndian(v);
}
class IPv6Address
mumber(成员变量)
// sockaddr_in6 结构体
sockaddr_in6 m_addr;
Create(通过IPv6地址字符串构造IPv6Address)
静态方法
IPv6Address::ptr IPv6Address::Create(const char* address, uint16_t port) {
IPv6Address::ptr rt(new IPv6Address);
rt->m_addr.sin6_port = byteswapOnLittleEndian(port);
int result = inet_pton(AF_INET6, address, &rt->m_addr.sin6_addr.__in6_u.__u6_addr8);
if (result <= 0) {
SYLAR_LOG_ERROR(g_logger) << "IPv4Address::Create(" << address << ", "
<< port << ") rt = " << result << " errno = " << errno
<< " strerror = " << strerror(errno);
return nullptr;
}
return rt;
}
IPv6Address(构造函数)
// 默认构造函数
IPv6Address::IPv6Address() {
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sin6_family = AF_INET6;
}
// 通过sockaddr_in6
IPv6Address::IPv6Address(const sockaddr_in6& sockaddr) {
m_addr = sockaddr;
}
// 通过address和port
IPv6Address::IPv6Address(const uint8_t address[16], uint16_t port) {
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sin6_family = AF_INET6;
m_addr.sin6_port = byteswapOnLittleEndian(port);
memcpy(&m_addr.sin6_addr.__in6_u.__u6_addr8, address, 16);
}
getAddr(返回sockaddr指针)
const sockaddr* IPv6Address::getAddr() const {
return (sockaddr*)&m_addr;
}
getAddrLen(返回sockaddr的长度)
socklen_t IPv6Address::getAddrLen() const {
return sizeof(m_addr);
}
insert(可读性输出地址)
std::ostream& IPv6Address::insert(std::ostream& os) const {
os << "[";
// 两个字节为一块
uint16_t* addr = (uint16_t*)m_addr.sin6_addr.__in6_u.__u6_addr8;
bool used_zeros = false;
for (int i = 0; i < 8; ++i) {
// 将连续0块省略
if (addr[i] == 0 && !used_zeros) {
continue;
}
// 上一块为0,多输出个:
if (i && addr[i - 1] == 0 && !used_zeros) {
os << ":";
// 省略过了,后面不能再省略连续0块了
used_zeros = true;
}
// 每个块后都要输出:
if (i) {
os << ":";
}
// 按十六进制输出
os << std::hex << (int)byteswapOnLittleEndian(addr[i]) << std::dec;
}
// 若最后一块为0省略
if (!used_zeros && addr[7] == 0) {
os << "::";
}
os << "]: " << byteswapOnLittleEndian(m_addr.sin6_port);
return os;
}
broadcastAddress(返回广播地址)
IPAddress::ptr IPv6Address::broadcastAddress(uint32_t prefix_len) {
sockaddr_in6 baddr(m_addr);
/* 找到前缀长度结尾在第几个字节,在该字节在哪个位置。
* 将该字节前剩余位置全部置为1 */
baddr.sin6_addr.__in6_u.__u6_addr8[prefix_len / 8] |=
~CreateMask<uint8_t>(prefix_len % 8);
// 将后面其余字节置为1
for (int i = prefix_len / 8 + 1; i < 16; ++i) {
baddr.sin6_addr.__in6_u.__u6_addr8[i] = 0xff;
}
return IPv6Address::ptr(new IPv6Address(baddr));
}
networkAddress(返回网络地址)
IPAddress::ptr IPv6Address::networkAddress(uint32_t prefix_len) {
sockaddr_in6 naddr(m_addr);
/* 找到前缀长度结尾在第几个字节,在该字节在哪个位置。
* 将该字节前剩余位置全部置为0 */
naddr.sin6_addr.__in6_u.__u6_addr8[prefix_len / 8] &=
CreateMask<uint8_t>(prefix_len % 8);
// 将后面其余字节置为0
for (int i = prefix_len / 8 + 1; i < 16; ++i) {
naddr.sin6_addr.__in6_u.__u6_addr8[i] = 0x00;
}
return IPv6Address::ptr(new IPv6Address(naddr));
}
subnetMask(返回子网掩码地址)
IPAddress::ptr IPv6Address::subnetMask(uint32_t prefix_len) {
sockaddr_in6 subnet;
memset(&subnet, 0, sizeof(subnet));
subnet.sin6_family = AF_INET6;
/* 找到前缀长度结尾在第几个字节,在该字节在哪个位置 */
subnet.sin6_addr.__in6_u.__u6_addr8[prefix_len / 8] =
CreateMask<uint8_t>(prefix_len % 8);
// 将前面的字节全部置为1
for (int i = 0; i < (int32_t)prefix_len / 8; ++i) {
subnet.sin6_addr.__in6_u.__u6_addr8[i] = 0xff;
}
return IPv6Address::ptr(new IPv6Address(subnet));
}
getPort(返回端口号)
uint16_t IPv6Address::getPort() const {
return byteswapOnLittleEndian(m_addr.sin6_port);
}
setPort(设置端口号)
void IPv6Address::setPort(uint16_t v) {
m_addr.sin6_port = byteswapOnLittleEndian(v);
}
class UinxAddress
mumber(成员变量)
// sockaddr_un 结构体
struct sockaddr_un m_addr;
// 长度
socklen_t m_length;
UinxAddress(构造函数)
// Unix域套接字路径名的最大长度。-1是减去'\0'
static const size_t MAX_PATH_LEN = sizeof(((sockaddr_un*)0)->sun_path) - 1;
// 默认构造
UinxAddress::UinxAddress() {
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sun_family = AF_UNIX;
// sun_path的偏移量+最大路径
m_length = offsetof(sockaddr_un, sun_path) + MAX_PATH_LEN;
}
// 通过路径
UinxAddress::UinxAddress(const std::string& path) {
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sun_family = AF_UNIX;
// 加上'\0'的长度
m_length = path.size() + 1;
if (!path.empty() && path[0] == '\0') {
--m_length;
}
if (m_length > sizeof(m_addr.sun_path)) {
throw std::logic_error("path too long");
}
// 将path放入结构体
memcpy(m_addr.sun_path, path.c_str(), m_length);
// 偏移量+路径长度
m_length += offsetof(sockaddr_un, sun_path);
}
getAddrLen(设置sockaddr的长度)
void UinxAddress::setAddrlen(uint32_t v) {
m_length = v;
}
getAddr(返回sockaddr指针)
const sockaddr* UinxAddress::getAddr() const {
return (sockaddr*)&m_addr;
}
getAddrLen(返回sockaddr的长度)
socklen_t UinxAddress::getAddrLen() const {
return m_length;
}
insert(可读性输出地址)
std::ostream& UinxAddress::insert(std::ostream& os) const {
if (m_length > offsetof(sockaddr_un, sun_path)
&& m_addr.sun_path[0] == '\0') {
return os << "\0" << std::string(m_addr.sun_path + 1,
m_length - offsetof(sockaddr_un, sun_path) - 1);
}
return os << m_addr.sun_path;
}
总结
通过静态方法能够通过域名、IP、主机名获得对应Address
void test() {
SYLAR_LOG_INFO(g_logger) << "begin";
std::vector<sylar::Address::ptr> addrs;
bool v = sylar::Address::Lookup(addrs, "www.baidu.com", AF_INET, SOCK_STREAM);
if (!v) {
SYLAR_LOG_ERROR(g_logger) << "lookup fail";
}
for (size_t i = 0; i < addrs.size(); ++i) {
SYLAR_LOG_INFO(g_logger) << i << " - " << addrs[i]->toString();
}
}
通过静态方法获得本机的Address
void test_iface() {
std::multimap<std::string, std::pair<sylar::Address::ptr, uint32_t> >results;
bool v = sylar::Address::GetInterfaceAddresses(results);
if (!v) {
SYLAR_LOG_ERROR(g_logger) << "GetInterfaceAddresses fail";
}
for (auto& i : results) {
SYLAR_LOG_INFO(g_logger) << i.first << " - " << i.second.first->toString() << " - " << i.second.second;
}
}
通过静态方法获取IPAddress
void test_ip() {
auto addr = sylar::IPAddress::Create("www.baidu.com");
if (addr) {
SYLAR_LOG_INFO(g_logger) << addr->toString();
}
}
创建IPv4地址
void test_ipv4() {
auto addr = sylar::IPv4Address::Create("112.80.248.75", 80);
auto saddr = addr->subnetMask(24);
auto baddr = addr->broadcastAddress(24);
auto naddr = addr->networkAddress(24);
if (addr) {
SYLAR_LOG_INFO(g_logger) << addr->toString();
}
if (saddr) {
SYLAR_LOG_INFO(g_logger) << saddr->toString();
}
if (baddr) {
SYLAR_LOG_INFO(g_logger) << baddr->toString();
}
if (naddr) {
SYLAR_LOG_INFO(g_logger) << naddr->toString();
}
}
创建IPv6地址
void test_ipv6() {
auto addr = sylar::IPv6Address::Create("fe80::215:5dff:fe20:e26a", 8020);
if (addr) {
SYLAR_LOG_INFO(g_logger) << addr->toString();
}
auto saddr = addr->subnetMask(64);
auto baddr = addr->broadcastAddress(64);
auto naddr = addr->networkAddress(64);
if (addr) {
SYLAR_LOG_INFO(g_logger) << addr->toString();
}
if (saddr) {
SYLAR_LOG_INFO(g_logger) << saddr->toString();
}
if (baddr) {
SYLAR_LOG_INFO(g_logger) << baddr->toString();
}
if (naddr) {
SYLAR_LOG_INFO(g_logger) << naddr->toString();
}
}