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

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

简介

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

NetAddressList的定义

 class NetAddressList {
public:
// 构造函数hostname可以是一个点分十进制的IP地址,也可以是主机域名
NetAddressList(char const* hostname);
NetAddressList(NetAddressList const& orig);
NetAddressList& operator=(NetAddressList const& rightSide);
virtual ~NetAddressList();
//获取地址表中元素个数
unsigned numAddresses() const { return fNumAddresses; }
//获取地址表第一个地址的内存地址
NetAddress const* firstAddress() const; // Used to iterate through the addresses in a list:
// 用于遍历列表中的地址:
class Iterator {
public:
Iterator(NetAddressList const& addressList);
NetAddress const* nextAddress(); // NULL iff none没有跟多地址了
private:
NetAddressList const& fAddressList; //必须绑定一个地址表
unsigned fNextIndex; //下一个地址的索引
}; private:
//为地址表申请内存空间,并将表addressArray中的内容拷贝进去
void assign(netAddressBits numAddresses, NetAddress** addressArray);
//删除地址表和地址表中所有地址
void clean(); friend class Iterator;
unsigned fNumAddresses; //地址个数
NetAddress** fAddressArray; //地址表
};

NetAddressList 定义

assign方法

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

 void NetAddressList::assign(unsigned numAddresses, NetAddress** addressArray) {
//为地址表分配内存空间
fAddressArray = new NetAddress*[numAddresses];
if (fAddressArray == NULL) {
fNumAddresses = ;
return;
}
//为地址表每个地址分配内存空间
for (unsigned i = ; i < numAddresses; ++i) {
fAddressArray[i] = new NetAddress(*addressArray[i]);
}
fNumAddresses = numAddresses;
}

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函数来获取它的所有地址。然后分配空间拷贝保存了这些地址。

 NetAddressList::NetAddressList(char const* hostname)
: fNumAddresses(), fAddressArray(NULL) {
// First, check whether "hostname" is an IP address string:
// 首先,检查“hostname”是否是一个IP地址字符串
netAddressBits addr = our_inet_addr((char*)hostname);
if (addr != INADDR_NONE) {
// Yes, it was an IP address string. Return a 1-element list with this address:
//它是一个IP地址字符串,那么这个地址表只需要1个元素
fNumAddresses = ;
fAddressArray = new NetAddress*[fNumAddresses];
if (fAddressArray == NULL) return;
//申请空间,保存这个地址。注意保存的是整数地址而不是字符串
fAddressArray[] = new NetAddress((u_int8_t*)&addr, sizeof (netAddressBits));
return;
} // "hostname" is not an IP address string; try resolving it as a real host name instead:
// 当它不是一个IP地址字符串,尝试解析hostname真实的地址来代替
#if defined(USE_GETHOSTBYNAME) || defined(VXWORKS)
struct hostent* host;
#if defined(VXWORKS)
char hostentBuf[]; host = (struct hostent*)resolvGetHostByName((char*)hostname, (char*)&hostentBuf, sizeof hostentBuf);
#else
//gethostbyname()返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针(不要试图delete这个返回的地址)
host = gethostbyname((char*)hostname);
#endif
if (host == NULL || host->h_length != || host->h_addr_list == NULL) return; // no luck //不幸,没有得到 u_int8_t const** const hAddrPtr = (u_int8_t const**)host->h_addr_list;
// First, count the number of addresses:取得地址个数
u_int8_t const** hAddrPtr1 = hAddrPtr;
while (*hAddrPtr1 != NULL) {
++fNumAddresses;
++hAddrPtr1;
} // Next, set up the list: 给地址表分配内存
fAddressArray = new NetAddress*[fNumAddresses];
if (fAddressArray == NULL) return;
//逐个拷贝地址到地址表
for (unsigned i = ; i < fNumAddresses; ++i) {
fAddressArray[i] = new NetAddress(hAddrPtr[i], host->h_length);
}
#else
// Use "getaddrinfo()" (rather than the older, deprecated "gethostbyname()"):
struct addrinfo addrinfoHints;
memset(&addrinfoHints, , sizeof addrinfoHints);
addrinfoHints.ai_family = AF_INET; // For now, we're interested in IPv4 addresses only
struct addrinfo* addrinfoResultPtr = NULL;
int result = getaddrinfo(hostname, NULL, &addrinfoHints, &addrinfoResultPtr);
if (result != || addrinfoResultPtr == NULL) return; // no luck // First, count the number of addresses:
const struct addrinfo* p = addrinfoResultPtr;
while (p != NULL) {
if (p->ai_addrlen < ) continue; // sanity check: skip over addresses that are too small
++fNumAddresses;
p = p->ai_next;
} // Next, set up the list:
fAddressArray = new NetAddress*[fNumAddresses];
if (fAddressArray == NULL) return; unsigned i = ;
p = addrinfoResultPtr;
while (p != NULL) {
if (p->ai_addrlen < ) continue;
fAddressArray[i++] = new NetAddress((u_int8_t const*)&(((struct sockaddr_in*)p->ai_addr)->sin_addr.s_addr), );
p = p->ai_next;
} // Finally, free the data that we had allocated by calling "getaddrinfo()":
freeaddrinfo(addrinfoResultPtr);
#endif
}

NetAddressList 构造函数

clean方法与析构

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

 void NetAddressList::clean() {
while (fNumAddresses-- > ) { //逐个删除地址
delete fAddressArray[fNumAddresses];
}
//释放地址表
delete[] fAddressArray; fAddressArray = NULL;
}

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

 NetAddressList::~NetAddressList() {
clean();
}

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

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

 NetAddressList::NetAddressList(NetAddressList const& orig) {
assign(orig.numAddresses(), orig.fAddressArray);
} NetAddressList& NetAddressList::operator=(NetAddressList const& rightSide) {
if (&rightSide != this) {
clean();
assign(rightSide.numAddresses(), rightSide.fAddressArray);
}
return *this;
}

NetAddressList::Iterator迭代器

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

 NetAddressList::Iterator::Iterator(NetAddressList const& addressList)
: fAddressList(addressList), fNextIndex() {} NetAddress const* NetAddressList::Iterator::nextAddress() {
if (fNextIndex >= fAddressList.numAddresses()) return NULL; // no more
return fAddressList.fAddressArray[fNextIndex++];
}

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

  1. 32 GroupSock(AddressPortLookupTable)——live555源码阅读(四)网络

    32 GroupSock(AddressPortLookupTable)——live555源码阅读(四)网络 32 GroupSock(AddressPortLookupTable)——live555 ...

  2. 31 GroupSock(AddressString)——live555源码阅读(四)网络

    31 GroupSock(AddressString)——live555源码阅读(四)网络 31 GroupSock(AddressString)——live555源码阅读(四)网络 简介 Addre ...

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

    30 GroupSock(Port)——live555源码阅读(四)网络 30 GroupSock(Port)——live555源码阅读(四)网络 简介 Port类的定义 Port的构造与全局的 &l ...

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

    28 GroupSock(NetAddress)——live555源码阅读(四)网络 28 GroupSock(NetAddress)——live555源码阅读(四)网络 简介 1) NetAddre ...

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

    27 GroupSock概述(一)——live555源码阅读(四)网络 27 GroupSock概述(一)——live555源码阅读(四)网络 简介 1.网络通用数据类型定义 2.Tunnel隧道封装 ...

  6. 40 网络相关函数(八)——live555源码阅读(四)网络

    40 网络相关函数(八)——live555源码阅读(四)网络 40 网络相关函数(八)——live555源码阅读(四)网络 简介 15)writeSocket向套接口写数据 TTL的概念 函数send ...

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

    39 网络相关函数(七)——live555源码阅读(四)网络 39 网络相关函数(七)——live555源码阅读(四)网络 简介 14)readSocket从套接口读取数据 recv/recvfrom ...

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

    38 网络相关函数(六)——live555源码阅读(四)网络 38 网络相关函数(六)——live555源码阅读(四)网络 简介 12)makeSocketNonBlocking和makeSocket ...

  9. 37 网络相关函数(五)——live555源码阅读(四)网络

    37 网络相关函数(五)——live555源码阅读(四)网络 37 网络相关函数(五)——live555源码阅读(四)网络 简介 10)MAKE_SOCKADDR_IN构建sockaddr_in结构体 ...

随机推荐

  1. 转移大于2m的pdf文件到另外一个文件夹

    转移大于2m的pdf文件到另外一个文件夹 remove_moret2M_pdfs.py # -*- coding: utf-8 -*- """ Created on Mo ...

  2. JavaScript排序算法——希尔排序

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. How to read a scientific paper

    How to read a scientific paper Nothing makes you feel stupid quite like reading a scientific journal ...

  4. ecshop 网站标题不更新或内容不更新

    网站标题不更新,这种情况一般出在网站搬家的过程中,把以前的所有配置文件一起都搬到新的服务器上了. 网站状态: 后台店铺标题已经修改,前台不显示,数据shop_config 的shop_title能更新 ...

  5. DNS域传送漏洞利用

    DNS区域传送(DNS zone transfer)指的是一台备用服务器使用来自主服务器的数据刷新自己的域(zone)数据库.这为运行中的DNS服务提供了一定的冗余度,其目的是为了防止主的域名服务器因 ...

  6. 浅谈JavaScript中的能力检测

    引言 我们知道,各个版本的浏览器有着许多不一致性.理想状态下,应该是所有的浏览器都提供一套标准的API接口.但是现实中,各个版本的浏览器存在的怪癖非常多,我们通常都是使用客户端检测来作为补救措施.但是 ...

  7. Loader Generator---loading图片生成器

    if(公司配有专业的设计师) return; Recommend("http://loadergenerator.com/");

  8. 遍历JObject

    JObject jo = JObject.Parse(jsonStr); IEnumerable<JProperty> properties = jo.Properties(); fore ...

  9. 妈咪,我找到了! -- 15个实用的Linux find命令示例

    妈咪,我找到了! -- 15个实用的Linux find命令示例 英文原文:Mommy, I found it! — 15 Practical Linux Find Command Examples ...

  10. Java中Office(word/ppt/excel)转换成HTML实现

    运行条件:JDK + jacob.jar + jacob.dll 1) 把jacob.dll在 JAVA_HOME\bin\ 和 JAVA_HOME\jre\bin\ 以及C:\WINDOWS\sys ...