zoukankan      html  css  js  c++  java
  • 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对象。

    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库函数),其定义在live555sourcecontrolgroupsockinet.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 }
  • 相关阅读:
    xpath和lxml库
    pipenv和autoenv
    正则表达式
    requests库
    Photoshop学习笔记
    Firebug使用笔记
    JavaScript中的声明提升(Hoisting )
    JavaScript中的继承机制
    JavaScript中的instanceof原理详解
    JSP使用JSON传递数据,注意避免中文乱码
  • 原文地址:https://www.cnblogs.com/oloroso/p/4613361.html
Copyright © 2011-2022 走看看