Address模块
- address模块概述
- address模块实现
- 其他
address模块概述
这一部分主要是为后面的网络模块进行服务了,其主要作用就针对IPv4、IPv6、Unix的网络地址进行一系列封装和方法的实现,通过统一的对外接口实现网络地址的相关查询等,方便了后续socket等模块的实现。
本人感觉从这一模块开始,sylar的代码阅读难度就没有之前那么难了,更多的是功能的实现、接口的封装等,相比于IO协程调度、定时器等这些理解有难度的模块,可以说是简单了一些。
address模块实现
从基类开始阅读吧就:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51// 网络地址的基类,抽象类 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
这些大多是基于其实现。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83bool 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地址的基类创建:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// 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; };
其中
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29IPAddress::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服务器框架内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复