Live555源码阅读笔记(四):groupsock 目录详解
一、groupsock 目录介绍
groupsock 目录总共有16个源码文件,编译后生成 libgroupsock.a,这个库中的类封装了网络接口和套接字,特别是“Groupsock”类封装了一个用于发送/或接收多播数据报的套接字。libgroupsock.a 作为live555的网络库,包含了TCP套接字和UDP套接字的创建以及收发数据,还实现了单播、多播,但代码量却很少,还是值得一看的。里面涉及很多基础网络编程知识,基础薄弱的同学阅读过后对网络编程会有新的了解。这篇文件旨在梳理这16个文件的逻辑关系和框架,帮助读者更好阅读源码。
二、阅读源码
阅读源码前,先看一下 Groupsock 的协作图,图中实线表示继承,虚线表示有该类的成员变量。可见,Groupsock 继承自 OutputSocket,OutputSocke 继承自 Socket,Socket 继承自 NetInterface。而 Groupsock 又有 GroupEId类、destRecord类、NetInterfaceTrafficStats类 的对象。其他的依此类推。对协作图有个大概了解后,下面看看几个主要的类以及主要的实现文件。
1、GroupEId 类
GroupEId 类主要是对多播地址进行封装,用于创建一个多播地址(IP地址、端口号、源地址、TTL)
1.1、GroupEId 类的属性
private:struct in_addr fGroupAddress; // IP地址struct in_addr fSourceFilterAddress;// 源地址portNumBits fPortNum; // 端口号(使用网络字节序)u_int8_t fTTL; // Time To Live的缩写,表示IP包被路由器丢弃之前允许通过的最大网段数量
1.2、GroupEId 类的方法
GroupEId 类的方法主要分为为2部分,一个是构造 源无关 或 指定源 多播地址,另一个是获取ip地址、源地址、端口、TTL的,代码实现也很简单,可以看以下注释。
public:// 构造一个 源无关 或 指定源 的多播地址GroupEId(struct in_addr const& groupAddr,portNumBits portNum, u_int8_t ttl);GroupEId(struct in_addr const& groupAddr,struct in_addr const& sourceFilterAddr,portNumBits portNum);struct in_addr const& groupAddress() const { return fGroupAddress; }// 获取IP地址struct in_addr const& sourceFilterAddress() const {return fSourceFilterAddress;}//指定源地址Boolean isSSM() const; // SSM(指定源组播)portNumBits portNum() const { return fPortNum; }// 获取端口号u_int8_t ttl() const { return fTTL; }private:void init(struct in_addr const& groupAddr,struct in_addr const& sourceFilterAddr,portNumBits portNum,u_int8_t ttl);
2、NetAddress.hh 和 NetAddress.cpp
这两个文件主要实现了几个类用于对ip地址、端口号的封装,以及域名解析等,下面简单介绍各个类的功能:
2.1、NetAddress 类
NetAddress 类是对IP地址的封装,成员变量(属性) fLength 表示该IP地址的字节数,fData 是一个指向IP地址的指针。
成员函数(方法)中有三个构造函数用于不同情况创建对象,主要函数注释如下
NetAddress(u_int8_t const* data,unsigned length = 4);// 根据data的数据构造IP地址
NetAddress(unsigned length = 4); // 构造一个0.0.0.0的IP地址
NetAddress(NetAddress const& orig);// 根据另一个对象构造地址
NetAddress& operator=(NetAddress const& rightSide);// 赋值运算符函数unsigned length() const { return fLength; }
u_int8_t const* data() const { return fData; } // always in network byte order
2.2、NetAddressList 类
NetAddressList 类主要用于域名解析,如果hostname是IP地址则返回一个元素的列表,如果是域名则返回该域名的所有IPV4地址的列表。
成员变量(属性) fNumAddresses 表示该IP地址列表的个数,fAddressArray 是一个指向IP地址列表的指针。
成员函数(方法)的各个实现看起来都挺简单的,没什么需要特别说明的,主要看懂构造函数里调用 gethostbyname 函数进行域名解析即可。
2.3、Port 类
对端口号进行封装。代码简单明了。
2.4、AddressPortLookupTable 类
AddressPortLookupTable 类是通过(地址1,地址2,端口)查找对象的通用表,内部是使用哈希表实现的,将“地址1,地址2,端口”合起来作为 key。
2.5、AddressString 类
AddressString 类可以接收 sockaddr_in、in_addr、netAddressBits 这三种类型的IP地址,并将该IP地址转为点分十进制的字符串(xxx.xxx.xxx.xxx),用来替换不是线程安全的 “inet_ntoa()”。
2.6、IsMulticastAddress 函数
IsMulticastAddress 函数用来判断是否为合法多播地址,多播路由器从不转发这个目的地址(224.0.0.0到224.0.0.255)的数据报。
3、NetInterface.hh 和 NetInterface.cpp
3.1、NetInterface 类
NetInterface 类是网络接口类,无提供接口方法,但有静态变量 DefaultUsageEnvironment,如果非 NULL,则用于每个新接口。
3.2、DirectedNetInterface 类
DirectedNetInterface类是定向网络接口类,提供了接口方法write、SourceAddrOKForRelaying。是 NetInterface类 的子类。
3.3、DirectedNetInterfaceSet 类
DirectedNetInterfaceSet 类是用于 DirectedNetInterface类 的定向网络接口表,内部实现是哈希表,用的 DirectedNetInterface 对象的地址作为 key。
3.4、Socket 类
Socket 类继承自 NetInterface类 ,是对套接字的封装,其构造函数根据端口号创建 udp 套接字,并保存到相关成员变量。由于构造函数是 protected 属性,不能直接实例化对象。
成员变量(属性) fSocketNum 记录创建成功的套接字,fPort 记录端口号,fEnv 记录使用环境相关的变量。
成员函数(方法)主要是创建套接字的,以及获取套接字、端口等,实现相对简单。
3.5、SocketLookupTable 类
SocketLookupTable 类是通过端口号查找 Socket类 对象的表,内部实现是哈希表。
3.6、NetInterfaceTrafficStats 类
NetInterfaceTrafficStats 类用于统计网络流量的。成员变量(属性) fTotNumPackets 表示总的包数,fTotNumBytes 表示总字节数。
4、OutputSocket 类
OutputSocket 类继承自 Socket类 ,默认情况下只用于发送数据,不会收到任何数据包。因为重写了父类的纯虚函数 handleRead ,所以 OutputSocket类 不是抽象类,且其构造函数是 public ,可以实例化。
成员属性(属性) fSourcePort 记录创建套接字时,内核指定的端口;fLastSentTTL 记录最后一次设置的TTL。
成员函数(方法)OutputSocket 创建 udp 套接字,端口号由内核指定。write 用于发送数据。
5、Groupsock 类
Groupsock 类用于发送和接收数据包。它最初是为发送/接收多播而设计的,但它也可以发送/接收单播。
方法:
public:
// 一、构造函数、析构函数
// 创建非特定源多播(组播)套接字:创建一个 UDP 套接字,并把本地ip地址加入到一个多播组中
Groupsock(UsageEnvironment& env,struct in_addr const& groupAddr,Port port,u_int8_t ttl);// 创建特定源多播(组播)套接字
Groupsock(UsageEnvironment& env, struct in_addr const& groupAddr,struct in_addr const& sourceFilterAddr,Port port);// 特定源多播virtual ~Groupsock();// 离开一个多播组// 二、目标地址记录相关
// 记录使用单链表实现的,这里会传入下个头节点的地址,并返回新建的节点的地址
virtual destRecord* createNewDestRecord(struct in_addr const& addr, Port const& port, u_int8_t ttl, unsigned sessionId, destRecord* next);// 修改“sessionId”对应的“destRecord”,sessionId不存在则添加一个新的“destRecord”。
void changeDestinationParameters(struct in_addr const& newDestAddr,Port newDestPort, int newDestTTL,unsigned sessionId = 0);// 根据目标地址查找目标记录
unsigned lookupSessionIdFromDestination(struct sockaddr_in const& destAddrAndPort) const;virtual void addDestination(struct in_addr const& addr, Port const& port, unsigned sessionId);// 向 fDests 添加目标记录
virtual void removeDestination(unsigned sessionId); // 从fDests链表删除指定 id 的目标
void removeAllDestinations(); // 清空目标记录
Boolean hasMultipleDestinations() const;// 有多个目标地址则返回true// 三、获取多播地址相关参数
struct in_addr const& groupAddress() const ;
struct in_addr const& sourceFilterAddress() const;
Boolean isSSM() const;
u_int8_t ttl() const;// 四、套接字发送相关
void multicastSendOnly();// 没有使用
virtual Boolean output(UsageEnvironment& env, unsigned char* buffer, unsigned bufferSize,DirectedNetInterface* interfaceNotToFwdBackTo = NULL);
DirectedNetInterfaceSet& members() { return fMembers; } // // 没有使用五、套接字读取相关
virtual Boolean handleRead(unsigned char* buffer, unsigned bufferMaxSize,unsigned& bytesRead,struct sockaddr_in& fromAddressAndPort);// 重写了套接字读取函数
6、GroupsockHelper.hh 和 GroupsockHelper.cpp
这两个文件是一些网络接口的底层实现,包括创建套接字、发送/接收数据、设置发送/接收缓冲区、设置阻塞/非阻塞、加入/退出多播组 等。
// 创建一个 UDP 套接字,并设置相应属性
int setupDatagramSocket(UsageEnvironment& env, Port port)// 创建 TCP 套接字,并设置 地址复用、端口复用
int setupStreamSocket(UsageEnvironment& env,Port port,Boolean makeNonBlocking,Boolean setKeepAlive)// 从套接字读取数据
int readSocket(UsageEnvironment& env,int socket,unsigned char* buffer,unsigned bufferSize,struct sockaddr_in& fromAddress)// 发送数据
Boolean writeSocket(UsageEnvironment& env,int socket, struct in_addr address, portNumBits portNum, unsigned char* buffer, unsigned bufferSize)// “发送或接收”缓冲区相关
unsigned getSendBufferSize(UsageEnvironment& env, int socket);
unsigned getReceiveBufferSize(UsageEnvironment& env, int socket);
unsigned setSendBufferTo(UsageEnvironment& env,int socket, unsigned requestedSize);
unsigned setReceiveBufferTo(UsageEnvironment& env,int socket, unsigned requestedSize);
unsigned increaseSendBufferTo(UsageEnvironment& env,int socket, unsigned requestedSize);
unsigned increaseReceiveBufferTo(UsageEnvironment& env,int socket,unsigned requestedSize);// 设置非阻塞
Boolean makeSocketNonBlocking(int sock)// 设置阻塞
Boolean makeSocketBlocking(int sock, unsigned writeTimeoutInMilliseconds)// 将 socket 加入多播组
Boolean socketJoinGroup(UsageEnvironment& env,int socket,netAddressBits groupAddress)// 将 socket 退出多播组
Boolean socketLeaveGroup(UsageEnvironment&, int socket,netAddressBits groupAddress)// 将 socket 加入“特定源”多播组 - SSM ( Source-Specific Multicast,特定源组播)
Boolean socketJoinGroupSSM(UsageEnvironment& env, int socket,netAddressBits groupAddress,netAddressBits sourceFilterAddr) // 将 socket 退出“特定源”多播组
Boolean socketLeaveGroupSSM(UsageEnvironment& /*env*/, int socket,netAddressBits groupAddress,netAddressBits sourceFilterAddr)
Live555源码阅读笔记(四):groupsock 目录详解相关推荐
- Live555源码阅读笔记(一):源码介绍文档 及 源码目录结构
目录 一.Live555介绍 1.Live555项目介绍 2.官网及帮助文档介绍 二.源码目录结构 1.UsageEnvironment 2.BasicUsageEnvironment 3.group ...
- Caddy源码阅读(一)Run详解
Caddy源码阅读(一)Run详解 前言 本次系列会讲解 caddy 整个生命周期涉及到的源码. 平时我们使用 caddy 都是使用 它的 二进制 分发文件,现在来分析 caddy 的 Run 函数. ...
- Werkzeug源码阅读笔记(四)
今天主要讲一下werkzeug中的routing模块.这个模块是werkzeug中的重点模块,Flask中的路由相关的操作使用的都是这个模块 routing模块的用法 在讲解模块的源码之前,先讲讲这个 ...
- 39 网络相关函数(七)——live555源码阅读(四)网络
39 网络相关函数(七)--live555源码阅读(四)网络 39 网络相关函数(七)--live555源码阅读(四)网络 简介 14)readSocket从套接口读取数据 recv/recvfrom ...
- 代码分析:NASM源码阅读笔记
NASM源码阅读笔记 NASM(Netwide Assembler)的使用文档和代码间的注释相当齐全,这给阅读源码 提供了很大的方便.按作者的说法,这是一个模块化的,可重用的x86汇编器, 而且能够被 ...
- syzkaller 源码阅读笔记1(syz-extract syz-sysgen)
文章目录 1. syz-extract 1-0 总结 1-1. `main()` 1-2 `archList()` - `1-1 (3)` 获取架构 name list 1-3 `createArch ...
- 24 UsageEnvironment使用环境抽象基类——Live555源码阅读(三)UsageEnvironment
24 UsageEnvironment使用环境抽象基类--Live555源码阅读(三)UsageEnvironment 24 UsageEnvironment使用环境抽象基类--Live555源码阅读 ...
- 16 BasicHashTable基本哈希表类(三)——Live555源码阅读(一)基本组件类
这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...
- CI框架源码阅读笔记4 引导文件CodeIgniter.php
到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http:// ...
最新文章
- 关系型数据库之Mysql备份(五)
- 聊聊storm的direct grouping
- Webpack学习-Loader
- stm32链接电脑提示无法识别的驱动设备
- 59.排序好的大数据创建索引文件,并实现大文件的二分查找,根据索引百万数据秒读数据...
- c++中vector使用的小问题
- [Objective-c 基础 - 2.5] .h和.m文件,点语法,成员变量作用域
- pdo_mysql未安装_php pdo_mysql未安装问题解决方法
- java 局部变量空间 大小_变量作用域-1:局部变量 和成员变量、各种变量内存分配的大小...
- 支持百万级TPS,Kafka是怎么做到的?
- Apache Server 修复两个高危缺陷
- [笔记]ASCLL码表(48 “0”,65 “A”,97 “a”)2022.3.12
- html鼠标自动向下滑动,win10电脑中鼠标自动向下或向上滚动怎么解决
- 大话数据结构Java版第一节
- python 会议室预约系统解决方案_会议室预约管理系统方案书.pdf
- 汽车之家所有车型价格爬虫
- 万兆网络传输速度测试_iperf测试万兆网卡tcp性能
- 普歌-云言团队-SSM系列与Spring框架入门
- 48 款数据可视化分析工具大集合
- 【c++】CTGU2022春校赛原题详解--可以冰墩墩一墩难求啊--单调栈