一、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 目录详解相关推荐

  1. Live555源码阅读笔记(一):源码介绍文档 及 源码目录结构

    目录 一.Live555介绍 1.Live555项目介绍 2.官网及帮助文档介绍 二.源码目录结构 1.UsageEnvironment 2.BasicUsageEnvironment 3.group ...

  2. Caddy源码阅读(一)Run详解

    Caddy源码阅读(一)Run详解 前言 本次系列会讲解 caddy 整个生命周期涉及到的源码. 平时我们使用 caddy 都是使用 它的 二进制 分发文件,现在来分析 caddy 的 Run 函数. ...

  3. Werkzeug源码阅读笔记(四)

    今天主要讲一下werkzeug中的routing模块.这个模块是werkzeug中的重点模块,Flask中的路由相关的操作使用的都是这个模块 routing模块的用法 在讲解模块的源码之前,先讲讲这个 ...

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

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

  5. 代码分析:NASM源码阅读笔记

    NASM源码阅读笔记 NASM(Netwide Assembler)的使用文档和代码间的注释相当齐全,这给阅读源码 提供了很大的方便.按作者的说法,这是一个模块化的,可重用的x86汇编器, 而且能够被 ...

  6. 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 ...

  7. 24 UsageEnvironment使用环境抽象基类——Live555源码阅读(三)UsageEnvironment

    24 UsageEnvironment使用环境抽象基类--Live555源码阅读(三)UsageEnvironment 24 UsageEnvironment使用环境抽象基类--Live555源码阅读 ...

  8. 16 BasicHashTable基本哈希表类(三)——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...

  9. CI框架源码阅读笔记4 引导文件CodeIgniter.php

    到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http:// ...

最新文章

  1. 关系型数据库之Mysql备份(五)
  2. 聊聊storm的direct grouping
  3. Webpack学习-Loader
  4. stm32链接电脑提示无法识别的驱动设备
  5. 59.排序好的大数据创建索引文件,并实现大文件的二分查找,根据索引百万数据秒读数据...
  6. c++中vector使用的小问题
  7. [Objective-c 基础 - 2.5] .h和.m文件,点语法,成员变量作用域
  8. pdo_mysql未安装_php pdo_mysql未安装问题解决方法
  9. java 局部变量空间 大小_变量作用域-1:局部变量 和成员变量、各种变量内存分配的大小...
  10. 支持百万级TPS,Kafka是怎么做到的?
  11. Apache Server 修复两个高危缺陷
  12. [笔记]ASCLL码表(48 “0”,65 “A”,97 “a”)2022.3.12
  13. html鼠标自动向下滑动,win10电脑中鼠标自动向下或向上滚动怎么解决
  14. 大话数据结构Java版第一节
  15. python 会议室预约系统解决方案_会议室预约管理系统方案书.pdf
  16. 汽车之家所有车型价格爬虫
  17. 万兆网络传输速度测试_iperf测试万兆网卡tcp性能
  18. 普歌-云言团队-SSM系列与Spring框架入门
  19. 48 款数据可视化分析工具大集合
  20. 【c++】CTGU2022春校赛原题详解--可以冰墩墩一墩难求啊--单调栈

热门文章

  1. PS Cloud:Odoo在中国唯一的SaaS营销平台
  2. 同样学习Linux, 为何差别这么大? - 论打通Linux进程和内存管理任督二脉
  3. SenseTime Ace Coder Challenge 暨 商汤在线编程挑战赛 B.我觉得海星
  4. 卡巴斯基郑启良:支持信创发展是卡巴斯基的重要使命
  5. Linux九阴真经之九阴白骨爪残卷14(备份和恢复)
  6. Activiti(基础)
  7. 《程序分析:开胃菜》概览
  8. 人生成败关键在于心态
  9. 中国工程院院士王国法:想实现煤炭完全无人化开采
  10. 【NOIP2016普及组】复赛——买铅笔