29 GroupSock(NetAddressList)——live555源码阅读(四)网络

29 GroupSock(NetAddressList)——live555源码阅读(四)网络

  • 29 GroupSock(NetAddressList)——live555源码阅读(四)网络

    • 简介
    • NetAddressList的定义
    • assign方法
    • NetAddressList的构造
    • clean方法与析构
    • 拷贝构造与赋值运算符重载
    • NetAddressList::Iterator迭代器

本文由乌合之众 lym瞎编,欢迎转载 blog.cnblogs.net/oloroso
本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso

简介

网络地址列表是用于保存一系列网络地址的类。它与NetAddress无直接联系。
NetAddressList类内部定义了一个二级指针NetAddress** fAddressArray,在使用的时候给它动态申请一个元素个数为unsigned fNumAddresses指针(NetAddress*)数组。指针数组的每一个元素又指向一个动态申请NetAddress对象。

NetAddressList的定义

 1 class NetAddressList {
 2 public:
 3     // 构造函数hostname可以是一个点分十进制的IP地址,也可以是主机域名
 4     NetAddressList(char const* hostname);
 5     NetAddressList(NetAddressList const& orig);
 6     NetAddressList& operator=(NetAddressList const& rightSide);
 7     virtual ~NetAddressList();
 8     //获取地址表中元素个数
 9     unsigned numAddresses() const { return fNumAddresses; }
10     //获取地址表第一个地址的内存地址
11     NetAddress const* firstAddress() const;
12
13     // Used to iterate through the addresses in a list:
14     // 用于遍历列表中的地址:
15     class Iterator {
16     public:
17         Iterator(NetAddressList const& addressList);
18         NetAddress const* nextAddress(); // NULL iff none没有跟多地址了
19     private:
20         NetAddressList const& fAddressList; //必须绑定一个地址表
21         unsigned fNextIndex;    //下一个地址的索引
22     };
23
24 private:
25     //为地址表申请内存空间,并将表addressArray中的内容拷贝进去
26     void assign(netAddressBits numAddresses, NetAddress** addressArray);
27     //删除地址表和地址表中所有地址
28     void clean();
29
30     friend class Iterator;
31     unsigned fNumAddresses;     //地址个数
32     NetAddress** fAddressArray; //地址表
33 };

NetAddressList 定义

assign方法

assign方法为地址表动态申请内存来保存地址元素。
要注意的是,这里所有的地址元素都是动态申请来的,所以释放的时候不知只释放fAddressArray指向的内存空间。

 1 void NetAddressList::assign(unsigned numAddresses, NetAddress** addressArray) {
 2     //为地址表分配内存空间
 3     fAddressArray = new NetAddress*[numAddresses];
 4     if (fAddressArray == NULL) {
 5         fNumAddresses = 0;
 6         return;
 7     }
 8     //为地址表每个地址分配内存空间
 9     for (unsigned i = 0; i < numAddresses; ++i) {
10         fAddressArray[i] = new NetAddress(*addressArray[i]);
11     }
12     fNumAddresses = numAddresses;
13 }

assign 方法

NetAddressList的构造

NetAddressList(char const* hostname)构造函数很长,内容不多,但是涉及到一些网络编程的基础知识。

首先参数hostname,是一个C风格的字符串,如果它保存的是一个点分十进制的IP地址(例如:”192.168.1.128”),那么只会给这个地址表申请一个元素的空间来保存地址。注意,保存的地址在一个NetAddress对象中,对象里面保存的是整型数形式的地址。

这里有一句netAddressBits addr = our_inet_addr((char*)hostname);这个函数的作用是把点分十进制的IP地址转换为整型数形式的地址。参数不是点分十进制的IP地址字符串,那么函数会返回错误码INADDR_NONEour_inet_addr实质上是调用的inet_addr(socket库函数),其定义在live555sourcecontrol\groupsock\inet.c文件中。

那如果参数hostname不是一个IP地址,那么它就应该是主机名(通常指域名,如live555.com)。一个域名可能对应不止一个IP地址(windows下可以使用nslookup命令查看,linux/unix下可以用dig命令)。这里使用了gethostbyname函数来获取它的所有地址。然后分配空间拷贝保存了这些地址。

 1 NetAddressList::NetAddressList(char const* hostname)
 2 : fNumAddresses(0), fAddressArray(NULL) {
 3     // First, check whether "hostname" is an IP address string:
 4     // 首先,检查“hostname”是否是一个IP地址字符串
 5     netAddressBits addr = our_inet_addr((char*)hostname);
 6     if (addr != INADDR_NONE) {
 7         // Yes, it was an IP address string.  Return a 1-element list with this address:
 8         //它是一个IP地址字符串,那么这个地址表只需要1个元素
 9         fNumAddresses = 1;
10         fAddressArray = new NetAddress*[fNumAddresses];
11         if (fAddressArray == NULL) return;
12         //申请空间,保存这个地址。注意保存的是整数地址而不是字符串
13         fAddressArray[0] = new NetAddress((u_int8_t*)&addr, sizeof (netAddressBits));
14         return;
15     }
16
17     // "hostname" is not an IP address string; try resolving it as a real host name instead:
18     // 当它不是一个IP地址字符串,尝试解析hostname真实的地址来代替
19 #if defined(USE_GETHOSTBYNAME) || defined(VXWORKS)
20     struct hostent* host;
21 #if defined(VXWORKS)
22     char hostentBuf[512];
23
24     host = (struct hostent*)resolvGetHostByName((char*)hostname, (char*)&hostentBuf, sizeof hostentBuf);
25 #else
26     //gethostbyname()返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针(不要试图delete这个返回的地址)
27     host = gethostbyname((char*)hostname);
28 #endif
29     if (host == NULL || host->h_length != 4 || host->h_addr_list == NULL) return; // no luck      //不幸,没有得到
30
31     u_int8_t const** const hAddrPtr = (u_int8_t const**)host->h_addr_list;
32     // First, count the number of addresses:取得地址个数
33     u_int8_t const** hAddrPtr1 = hAddrPtr;
34     while (*hAddrPtr1 != NULL) {
35         ++fNumAddresses;
36         ++hAddrPtr1;
37     }
38
39     // Next, set up the list: 给地址表分配内存
40     fAddressArray = new NetAddress*[fNumAddresses];
41     if (fAddressArray == NULL) return;
42     //逐个拷贝地址到地址表
43     for (unsigned i = 0; i < fNumAddresses; ++i) {
44         fAddressArray[i] = new NetAddress(hAddrPtr[i], host->h_length);
45     }
46 #else
47     // Use "getaddrinfo()" (rather than the older, deprecated "gethostbyname()"):
48     struct addrinfo addrinfoHints;
49     memset(&addrinfoHints, 0, sizeof addrinfoHints);
50     addrinfoHints.ai_family = AF_INET; // For now, we‘re interested in IPv4 addresses only
51     struct addrinfo* addrinfoResultPtr = NULL;
52     int result = getaddrinfo(hostname, NULL, &addrinfoHints, &addrinfoResultPtr);
53     if (result != 0 || addrinfoResultPtr == NULL) return; // no luck
54
55     // First, count the number of addresses:
56     const struct addrinfo* p = addrinfoResultPtr;
57     while (p != NULL) {
58         if (p->ai_addrlen < 4) continue; // sanity check: skip over addresses that are too small
59         ++fNumAddresses;
60         p = p->ai_next;
61     }
62
63     // Next, set up the list:
64     fAddressArray = new NetAddress*[fNumAddresses];
65     if (fAddressArray == NULL) return;
66
67     unsigned i = 0;
68     p = addrinfoResultPtr;
69     while (p != NULL) {
70         if (p->ai_addrlen < 4) continue;
71         fAddressArray[i++] = new NetAddress((u_int8_t const*)&(((struct sockaddr_in*)p->ai_addr)->sin_addr.s_addr), 4);
72         p = p->ai_next;
73     }
74
75     // Finally, free the data that we had allocated by calling "getaddrinfo()":
76     freeaddrinfo(addrinfoResultPtr);
77 #endif
78 }

NetAddressList 构造函数

clean方法与析构

先说clean方法,它的作用是将地址表和表中所有的地址元素都释放了。之前assign分配空间,在这里对应的释放。

1 void NetAddressList::clean() {
2     while (fNumAddresses-- > 0) {   //逐个删除地址
3         delete fAddressArray[fNumAddresses];
4     }
5     //释放地址表
6     delete[] fAddressArray; fAddressArray = NULL;
7 }

析构函数就是简单的调用clean

1 NetAddressList::~NetAddressList() {
2     clean();
3 }

拷贝构造与赋值运算符重载

这里就不多说了,代码很明白。(有人问赋值和拷贝构造的区别,这里简单说一下。拷贝构造的重点在于构造,是对象还没有的时候调用来创建一个一样的对象的,而赋值的重点在于赋值,是对象已经存在的时候,用来替换对象数据的。)

 1 NetAddressList::NetAddressList(NetAddressList const& orig) {
 2     assign(orig.numAddresses(), orig.fAddressArray);
 3 }
 4
 5 NetAddressList& NetAddressList::operator=(NetAddressList const& rightSide) {
 6     if (&rightSide != this) {
 7         clean();
 8         assign(rightSide.numAddresses(), rightSide.fAddressArray);
 9     }
10     return *this;
11 }

NetAddressList::Iterator迭代器

这里的迭代器与之前的HanlerSet类和DelayQueue很像。这里NetAddressList::IteratorNetAddressList类内部嵌套定义的类,权限是public。在构造的时候,其也需要绑定一个NetAddressList对象,迭代器方法nextAddress返回类型是NetAddress const*,这里要注意一下。

1 NetAddressList::Iterator::Iterator(NetAddressList const& addressList)
2 : fAddressList(addressList), fNextIndex(0) {}
3
4 NetAddress const* NetAddressList::Iterator::nextAddress() {
5     if (fNextIndex >= fAddressList.numAddresses()) return NULL; // no more
6     return fAddressList.fAddressArray[fNextIndex++];
7 }
时间: 2024-10-16 23:50:32

29 GroupSock(NetAddressList)——live555源码阅读(四)网络的相关文章

30 GroupSock(Port)——live555源码阅读(四)网络

30 GroupSock(Port)——live555源码阅读(四)网络 30 GroupSock(Port)——live555源码阅读(四)网络 简介 Port类的定义 Port的构造与全局的 << 运算符重载 本文由乌合之众 lym瞎编,欢迎转载 blog.cnblogs.net/oloroso 本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso 简介 端口类是用于保存网络端口的,计算机网络端口一般有两种含义,分别是物理意义上的网络设备接口和逻辑意义上的端口

28 GroupSock(NetAddress)——live555源码阅读(四)网络

28 GroupSock(NetAddress)——live555源码阅读(四)网络 28 GroupSock(NetAddress)——live555源码阅读(四)网络 简介 1) NetAddress网络地址类简述 下面是其定义 assign方法(分配空间) NetAddress的构造 clean方法(清理)与析构 operate= 重载赋值操作 本文由乌合之众 lym瞎编,欢迎转载 blog.cnblogs.net/oloroso 本文由乌合之众 lym瞎编,欢迎转载 my.oschina

27 GroupSock概述(一)——live555源码阅读(四)网络

27 GroupSock概述(一)——live555源码阅读(四)网络 27 GroupSock概述(一)——live555源码阅读(四)网络 简介 1.网络通用数据类型定义 2.Tunnel隧道封装 本文由乌合之众 lym瞎编,欢迎转载 blog.cnblogs.net/oloroso 本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso 简介 group是组/群的意思,socket是网络接口的代名词了.这个部分很庞大,主要是与网络相关的.而live555的网络模

39 网络相关函数(七)——live555源码阅读(四)网络

39 网络相关函数(七)——live555源码阅读(四)网络 39 网络相关函数(七)——live555源码阅读(四)网络 简介 14)readSocket从套接口读取数据 recv/recvfrom 函数 函数原型: 参数说明: 返回说明: 本文由乌合之众 lym瞎编,欢迎转载 blog.cnblogs.net/oloroso 本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso 简介 网络相关函数是一系列用于操作网络数据的函数.在多个文件中都有相关的函数的定义.

38 网络相关函数(六)——live555源码阅读(四)网络

38 网络相关函数(六)——live555源码阅读(四)网络 38 网络相关函数(六)——live555源码阅读(四)网络 简介 12)makeSocketNonBlocking和makeSocketBlocking套接口阻塞属性设置 13)setupStreamSocket设置流式套接口 本文由乌合之众 lym瞎编,欢迎转载 blog.cnblogs.net/oloroso 本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso 简介 网络相关函数是一系列用于操作网

SDWebImage源码阅读(四)SDWebImageDecoder

一般我们都是使用: 1 + (nullable UIImage *)imageNamed:(NSString *)name; // load from main bundle 和: 1 + (nullable UIImage *)imageWithContentsOfFile:(NSString *)path; 两种方式加载图片,它们两个的区别在SDWebImage源码阅读前的准备(三)UIImage.h 里面的 "(六):加载和创建UIImage 的类方法和实例方法:"部分有详细的介

Spring源码阅读四 IOC

前面讲了 简单的实现方式通过FileSystemXmlApplicationContext这个类来实现,那么今天看下这个类做了什么,是如何完成IOC的? 上代码: public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(c

Struts2源码阅读(一)_Struts2框架流程概述

1. Struts2架构图  当外部的httpservletrequest到来时 ,初始到了servlet容器(所以虽然Servlet和Action是解耦合的,但是Action依旧能够通过httpservletrequest取得请求参数), 然后通过Filter chain,Filter主要包括ActionContextCleanUp,它主要清理当前线程的ActionContext和 Dispatcher:FilterDispatcher主要通过AcionMapper来决定需要调用哪个Actio

【原】AFNetworking源码阅读(四)

[原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDelegate类所实现的NSURLSession相关的代理方法,甚至连dataTask.uploadTask.downloadTask这几个基本概念也没说.这一篇就是为了集中消灭这些遗留问题. 2. AFURLSessionManagerTaskDelegate的代理方法 此处实现的仍然是NSURLS