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. zabbix搭建

    首先创建zabbix组和用户 groupadd zabbix useradd -g zabbix zabbix mkdir -p /app/local/zabbix#然后创建zabbix编译安装目录 ...

  2. JavaScript格式化日期

    查找格式化日期的方法大都是写日期扩展方法,也许是为了维持jquery easyUI 源码完整性, // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h ...

  3. 20145212 《Java程序设计》第6周学习总结

    20145212 <Java程序设计>第6周学习总结 学习内容总结 第十章 1.Java将输入/输出抽象化为串流.读取数据对象成为输入流,能向其写入的对象叫输出流. 我从网上找到了一个可以 ...

  4. 转换流——OutputStreamWriter类与InputStreamReader类

    字节流和字符流的转换类 OutputStreamWriter:是Writer的子类,将输出的字符流变成字节流 InputStreamReader:是Reader的子类,将输入的字节流变成字符流 将字节 ...

  5. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【六】——实现资源间的关联

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 这一篇文章主要介绍一下资源间的关联——例如在学生和课程之间就存在这样的关联:每一个课程都会有 ...

  6. wordpress后台404页面

    就在刚刚,boss需要看公司网站后台,网站是用wordpress搭的,发现全是404,蛋疼,于是google,下面是解决办法: location / { if (-f $request_filenam ...

  7. yourphp 遇见问题及解决办法

    1.前台页面提交出现 __NOLAYOUT__ 解决把法: 在Public 文件下找到 success.html,error.html,exception.html 头部去掉就可以

  8. Python 之作用域和名字空间

    作用域与名字空间 Python有一个核心概念是名字空间(namespace),namespace是一个name到object 的映射关系,Python有很多namespace,因此,在代码中如果碰到一 ...

  9. Lua 之数据结构

    Lua 之数据结构 数组 通过整数下标访问的table中的元素,即是数组,下标默认从1开始. 一个创建二维数组的例子: mt = {} , do mt[i] = {} , do mt[i][j] = ...

  10. Python-面向对象编程(一)

    初识面向对象: Python中一切皆对象,我自己,我的电脑,电脑桌,都称之为一个对象.对象是类的一个实体. 我们可以通过行为和特征(属性)来描述一个对象,比如小狗,它有四条腿,一个尾巴,两个虎牙,这就 ...