概述
Address模块
- address模块概述
- address模块实现
- 其他
address模块概述
这一部分主要是为后面的网络模块进行服务了,其主要作用就针对IPv4、IPv6、Unix的网络地址进行一系列封装和方法的实现,通过统一的对外接口实现网络地址的相关查询等,方便了后续socket等模块的实现。
本人感觉从这一模块开始,sylar的代码阅读难度就没有之前那么难了,更多的是功能的实现、接口的封装等,相比于IO协程调度、定时器等这些理解有难度的模块,可以说是简单了一些。
address模块实现
从基类开始阅读吧就:
// 网络地址的基类,抽象类
class Address {
public:
typedef std::shared_ptr<Address> ptr;
// 通过sockaddr指针创建Address
static Address::ptr Create(const sockaddr* addr, socklen_t addrlen);
// 通过host地址返回对应条件的所有Address
static bool Lookup(std::vector<Address::ptr>& result, const std::string& host, int family = AF_INET, int type = 0, int protocol = 0);
// 通过host地址返回对应条件的任意Address
static Address::ptr LookupAny(const std::string& host, int family = AF_INET, int type = 0, int protocol = 0);
// 通过host地址返回对应条件的任意IPAddress
static std::shared_ptr<IPAddress> LookupAnyIPAddress(const std::string& host, int family = AF_INET, int type = 0, int protocol = 0);
// 返回本机所有网卡的<网卡名, 地址, 子网掩码位数>
static bool GetInterfaceAddresses(std::multimap<std::string, std::pair<Address::ptr, uint32_t> >& result, int family = AF_INET);
// 获取指定网卡的地址和子网掩码位数
static bool GetInterfaceAddresses(std::vector<std::pair<Address::ptr, uint32_t> >&result ,const std::string& iface, int family = AF_INET);
// 虚析构函数
virtual ~Address() {}
// 返回协议簇
int getFamily() const;
// 返回sockaddr指针,只读
virtual const sockaddr* getAddr() const = 0;
// 返回sockaddr指针,读写
virtual sockaddr* getAddr() = 0;
// 返回sockaddr的长度
virtual socklen_t getAddrLen() const = 0;
// 可读性输出地址
virtual std::ostream& insert(std::ostream& os) const = 0;
// 返回可读性字符串
std::string toString() const;
// 小于号比较函数
bool operator<(const Address& rhs) const;
// 等于函数
bool operator==(const Address& rhs) const;
// 不等于函数
bool operator!=(const Address& rhs) const;
};
其中,主要的方法是Lookup
方法和Create
方法,其他的LookupAnyLookupAnyIPAddressGetInterfaceAddresses
这些大多是基于其实现。
bool Address::Lookup(std::vector<Address::ptr>& result, const std::string& host,
int family, int type, int protocol) {
addrinfo hints, *results, *next;
hints.ai_flags = 0;
hints.ai_family = family;
hints.ai_socktype = type;
hints.ai_protocol = protocol;
hints.ai_addrlen = 0;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
std::string node;
const char* service = NULL;
//检查 ipv6address serivce
if(!host.empty() && host[0] == '[') {
// void *memchr(const void *str, int c, size_t n)
// 搜索参数str指向的字符串的前n个字节中第一次出现的字符c(unsigned char类型)。
const char* endipv6 = (const char*)memchr(host.c_str() + 1, ']', host.size() - 1);
if(endipv6) {
//TODO check out of range
if(*(endipv6 + 1) == ':') {
service = endipv6 + 2;
}
node = host.substr(1, endipv6 - host.c_str() - 1);
}
}
//检查 node serivce
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;
}
}
}
if(node.empty()) {
node = host;
}
// 处理名字到地址以及服务到端口这两种转换,返回的是一个addrinfo的结构(列表)指针而不是一个地址清单
int error = getaddrinfo(node.c_str(), service, &hints, &results);
if(error) {
SYLAR_LOG_DEBUG(g_logger) << "Address::Lookup getaddress(" << host << ", "
<< family << ", " << type << ") err=" << error << " errstr="
<< gai_strerror(error);
return false;
}
next = results;
while(next) {
result.push_back(Create(next->ai_addr, (socklen_t)next->ai_addrlen));
//SYLAR_LOG_INFO(g_logger) << ((sockaddr_in*)next->ai_addr)->sin_addr.s_addr;
next = next->ai_next;
}
// 释放空间
freeaddrinfo(results);
return !result.empty();
}
Address::ptr Address::Create(const sockaddr* addr, socklen_t addrlen) {
if(addr == nullptr) {
return nullptr;
}
Address::ptr result;
switch(addr->sa_family) {
case AF_INET:
result.reset(new IPv4Address(*(const sockaddr_in*)addr));
break;
case AF_INET6:
result.reset(new IPv6Address(*(const sockaddr_in6*)addr));
break;
default:
result.reset(new UnknownAddress(*addr));
break;
}
return result;
}
随后便是IP地址的基类创建:
// IP地址基类
class IPAddress : public Address {
public:
typedef std::shared_ptr<IPAddress> ptr;
/、 通过域名,IP,服务器名创建IPAddress
static IPAddress::ptr Create(const char* address, uint16_t port = 0);
// 获取该地址的广播地址
virtual IPAddress::ptr broadcastAddress(uint32_t prefix_len) = 0;
// 获取该地址的网段
virtual IPAddress::ptr networdAddress(uint32_t prefix_len) = 0;
// 获取子网掩码地址
virtual IPAddress::ptr subnetMask(uint32_t prefix_len) = 0;
// 返回端口号
virtual uint32_t getPort() const = 0;
// 设置端口号
virtual void setPort(uint16_t v) = 0;
};
其中
IPAddress::ptr IPAddress::Create(const char* address, uint16_t port) {
addrinfo hints, *results;
memset(&hints, 0, sizeof(addrinfo));
hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = AF_UNSPEC;
int error = getaddrinfo(address, NULL, &hints, &results);
if(error) {
SYLAR_LOG_DEBUG(g_logger) << "IPAddress::Create(" << address
<< ", " << port << ") error=" << error
<< " errno=" << errno << " errstr=" << strerror(errno);
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;
}
}
剩下的就是几个子类的实现和具体方法的实现了
其他
Address模块阅读起来并不算难,但是真的想掌握的话建议还是多看看源码,还有就是对一些系统方法要比较了解,感觉这一块就这样吧,如果后续结合socket等模块阅读之后感觉还有要补充的会再做补充。
最后
以上就是殷勤项链为你收集整理的[源码阅读]——Sylar服务器框架:Address模块的全部内容,希望文章能够帮你解决[源码阅读]——Sylar服务器框架:Address模块所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复