WebRTC源代码探索之旅——多线程篇(5 - 1)

来源:互联网 发布:期权看盘软件 编辑:程序博客网 时间:2024/05/04 10:04

5 physicalsocketserver

 

physicalsocketserver.h/physicalsocketserver.cc文件实现了一个基本的多路信号分离器。这个多路信号分离器的实现代码可以横跨Windows、Linux、OSX、Android、ios等平台,非常复杂。其实在/trunk/talk/base目录下,还有多个SocketServer的实现,从这些SocketServer的名字就可以看出是针对哪些平台特化实现,比如talk_base::MacCocoaSocketServer。在这里我就不对这些SocketServer进行分析,只要能够明白talk_base::PhysicalSocketServer的原理,再加上对平台API的了解应该很容易读懂这些平台特化的SocketServer。

 

在该文件中将大量使用socket相关的系统调用。由于本篇章的内容为多线程编程,所以尽量不做过多的涉及,并且忽略引用其他文件定义的socket相关类(比如talk_base::PhysicalSocket)。

 

5.1 talk_base::Dispatcher

 

该类定义了事件分发器的纯虚基类。事件分发器主要是将IO或Event信号对应到一定的处理函数上去。该纯虚基类在Windows和Posix2个平台下定义的函数接口有很大的区别。但是主要的功能大致差不多。

 

5.2 talk_base::PhysicalSocket

 

该类是physicalsocketserver.cc文件的内部私有的类,不对外暴露,它主要是对Socket的跨平台封装。由于Windows也提供了基本和BSDsocket一致的Socket API所以该类的代码不难理解。

 

talk_base::PhysicalSocket的主要组件包括:

s_:socket句柄/文件描述符

enabled_events_:需要监听的IO事件

udp_:通信方式是否为UDP

error_:最后出错码(Last Error)

state_:连接状态

resolver_:异步的网址解析器

 

talk_base::PhysicalSocket的主要成员函数包括:

构造函数:创建并初始化talk_base::PhysicalSocket对象

参数说明:

ss:管理的talk_base::SocketServer

s:封装的系统socket句柄/文件描述符;如果不提供该参数, talk_base::PhysicalSocket将创建一个;如果提供talk_base::PhysicalSocket将对其进行封装

 

talk_base::PhysicalSocket::Create:创建系统socket句柄/文件描述符

参数说明:

family:socket的寻址方案(AF_INET/AF_INET6);从这个参数可以看出WebRTC是支持IPV6的

type:socket的类型(TCP/UDP)

 

talk_base::PhysicalSocket::Connect:连接指定的地址和端口,如果地址尚未解析,调用异步的地址解析器

参数说明:

addr:需要连接的地址(使用talk_base::SocketAddress,该类包括地址和端口号)

 

talk_base::PhysicalSocket::EstimateMTU:获取socket连接的MTU(最大传输单元)

参数说明:

mtu:返回最大传输单元

返回值:出错码

原理:

Windows平台调用Ping库获取

IOS和OSX平台没有简单地方法获取,直接返回出错

Linux平台调用getsockopt(s_,IPPROTO_IP, IP_MTU, &value, &vlen)获取

 

由于Windows提供了基本和BSD socket一致的API,所以在Windows的代码和Linux的代码几乎一致。一下将简单对比一下API:

 

socket、getsocketname、getpeername、bind、connect、recv、recvfrom、accept、closesocket

Linux平台下完全一致

 

getsockopt、setsockopt

Linux平台下完全一致(仅有一些特殊的选项不同)

 

send、sendto

在Linux平台下将最后一个参数flag设置为MSG_NOSIGNAL,屏蔽SIGPIPE

 

talk_base::PhysicalSocket需要注意2点:

1虽然它继承自talk_base::AsyncSocket,但是它管理的内部系统socket句柄/描述符是阻塞的(它的子类talk_base::SocketDispatcher会将系统socket句柄/描述符转为非阻塞的)。继承自talk_base:: AsyncSocket的原因可能是为了避免多继承造成类继承结构过于复杂。

2虽然该类具有很多和talk_base::SocketServer相关的成员变量和成员函数,但是talk_base::PhysicalSocketServer不能直接管理talk_base::PhysicalSocket。能被talk_base::PhysicalSocketServer管理的是talk_base::PhysicalSocket的一个子类talk_base::SocketDispatcher,它也是一个physicalsocketserver.cc内部私有的一个类。

当然以上这2点只是实现的细节问题,这些类都是不对外暴露的,我们仅仅需要懂得如何使用对外暴露的接口就可以了。
0 0
原创粉丝点击