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

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

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

简介

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

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

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

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 }

 

你可能感兴趣的:(group)