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的定义
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)
构造函数很长,内容不多,但是涉及到一些网络编程的基础知识。
首先参数hostnam
e,是一个C风格
的字符串,如果它保存的是一个点分十进制的IP地址
(例如:”192.168.1.128”
),那么只会给这个地址表申请一个元素的空间来保存地址。注意,保存的地址在一个NetAddress
对象中,对象里面保存的是整型数形式的地址。
这里有一句netAddressBits addr = our_inet_addr((char*)hostname);
这个函数的作用是把点分十进制的IP地址转换为整型数形式的地址。参数不是点分十进制的IP地址字符串,那么函数会返回错误码INADDR_NONE
。our_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::Iterator
在NetAddressList
类内部嵌套定义的类,权限是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源码阅读(四)网络的更多相关文章
- 32 GroupSock(AddressPortLookupTable)——live555源码阅读(四)网络
32 GroupSock(AddressPortLookupTable)——live555源码阅读(四)网络 32 GroupSock(AddressPortLookupTable)——live555 ...
- 31 GroupSock(AddressString)——live555源码阅读(四)网络
31 GroupSock(AddressString)——live555源码阅读(四)网络 31 GroupSock(AddressString)——live555源码阅读(四)网络 简介 Addre ...
- 30 GroupSock(Port)——live555源码阅读(四)网络
30 GroupSock(Port)——live555源码阅读(四)网络 30 GroupSock(Port)——live555源码阅读(四)网络 简介 Port类的定义 Port的构造与全局的 &l ...
- 28 GroupSock(NetAddress)——live555源码阅读(四)网络
28 GroupSock(NetAddress)——live555源码阅读(四)网络 28 GroupSock(NetAddress)——live555源码阅读(四)网络 简介 1) NetAddre ...
- 27 GroupSock概述(一)——live555源码阅读(四)网络
27 GroupSock概述(一)——live555源码阅读(四)网络 27 GroupSock概述(一)——live555源码阅读(四)网络 简介 1.网络通用数据类型定义 2.Tunnel隧道封装 ...
- 40 网络相关函数(八)——live555源码阅读(四)网络
40 网络相关函数(八)——live555源码阅读(四)网络 40 网络相关函数(八)——live555源码阅读(四)网络 简介 15)writeSocket向套接口写数据 TTL的概念 函数send ...
- 39 网络相关函数(七)——live555源码阅读(四)网络
39 网络相关函数(七)——live555源码阅读(四)网络 39 网络相关函数(七)——live555源码阅读(四)网络 简介 14)readSocket从套接口读取数据 recv/recvfrom ...
- 38 网络相关函数(六)——live555源码阅读(四)网络
38 网络相关函数(六)——live555源码阅读(四)网络 38 网络相关函数(六)——live555源码阅读(四)网络 简介 12)makeSocketNonBlocking和makeSocket ...
- 37 网络相关函数(五)——live555源码阅读(四)网络
37 网络相关函数(五)——live555源码阅读(四)网络 37 网络相关函数(五)——live555源码阅读(四)网络 简介 10)MAKE_SOCKADDR_IN构建sockaddr_in结构体 ...
随机推荐
- zabbix搭建
首先创建zabbix组和用户 groupadd zabbix useradd -g zabbix zabbix mkdir -p /app/local/zabbix#然后创建zabbix编译安装目录 ...
- JavaScript格式化日期
查找格式化日期的方法大都是写日期扩展方法,也许是为了维持jquery easyUI 源码完整性, // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h ...
- 20145212 《Java程序设计》第6周学习总结
20145212 <Java程序设计>第6周学习总结 学习内容总结 第十章 1.Java将输入/输出抽象化为串流.读取数据对象成为输入流,能向其写入的对象叫输出流. 我从网上找到了一个可以 ...
- 转换流——OutputStreamWriter类与InputStreamReader类
字节流和字符流的转换类 OutputStreamWriter:是Writer的子类,将输出的字符流变成字节流 InputStreamReader:是Reader的子类,将输入的字节流变成字符流 将字节 ...
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【六】——实现资源间的关联
系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 这一篇文章主要介绍一下资源间的关联——例如在学生和课程之间就存在这样的关联:每一个课程都会有 ...
- wordpress后台404页面
就在刚刚,boss需要看公司网站后台,网站是用wordpress搭的,发现全是404,蛋疼,于是google,下面是解决办法: location / { if (-f $request_filenam ...
- yourphp 遇见问题及解决办法
1.前台页面提交出现 __NOLAYOUT__ 解决把法: 在Public 文件下找到 success.html,error.html,exception.html 头部去掉就可以
- Python 之作用域和名字空间
作用域与名字空间 Python有一个核心概念是名字空间(namespace),namespace是一个name到object 的映射关系,Python有很多namespace,因此,在代码中如果碰到一 ...
- Lua 之数据结构
Lua 之数据结构 数组 通过整数下标访问的table中的元素,即是数组,下标默认从1开始. 一个创建二维数组的例子: mt = {} , do mt[i] = {} , do mt[i][j] = ...
- Python-面向对象编程(一)
初识面向对象: Python中一切皆对象,我自己,我的电脑,电脑桌,都称之为一个对象.对象是类的一个实体. 我们可以通过行为和特征(属性)来描述一个对象,比如小狗,它有四条腿,一个尾巴,两个虎牙,这就 ...