WebRTC在进行互通的时候需要开放很多端口, 一个音/视频通道就要开启多个通道, 如果是多人音视频通话需要开通的端口更多. 对端口资源照成了很大的浪费, 一些防火墙会限制多udp端口的开放. 如果要部署在服务端, 多端口的开发会给运维照成极大的不方便.
目前为止已经有几个减少端口使用的策略:
这些策略都在不断的在消减端口的使用, 但即使上面的这些策略全部开启, 单个用户还是要占用最少一个端口, 如果一个WebRTC服务器要服务1000个用户, 就要开启1000个端口.
服务端使用单端口的策略有turnserver relay的方案, 这种方案的本质是在client->turnserver这条线路上turnserver通过单端口接受client的数据, 但在turnserver->webrtc mediaserver 这条线路上并没有减少端口的占用, mediaserver还是需要针对每个用户申请最少一个端口.
相比于rtmp直播服务器单端口走天下, webrtc mediaserver确实有点尴尬.
但是我们通过一些设计和策略也是可以让webrtc mediaserver只监听单端口的. 我们以https://github.com/medooze/media-server 中的实现为例, 介绍下webrtc mediaserver使用单端口的原理.
SDP里面包含ICE Info, 其中ice-ufrag可以作为唯一值对应一个connection, ufrag 会对应多个candidate, 在交换完offer和answer后, 服务端维护一个ufrag和connection的对应关系, 同时会维护一个candidate(client的ip和port)和connection的对应关系.
当服务端监听到远端的数据后, 可以得到远端的ip地址和port, 根据ip地址和port找到对应的conneciton. 这样就能区分远端的用户了.
通过进一步的处理解析出相对应的rtp header, 可以根据rtp header中的ssrc 找到对应的哪一路流, 就可以进行后续的处理了.
基本的流程图如下:
实际的交互过程会比这个更复杂一些, 有时候offer中可能并不包含candate, 可以根据stun binding request 拿到相应的ufrag和远端的ip和地址.
需要注意的是, 这样的模型对于client -> server直接交互的状态下没有什么问题, 但对于多个WebRTC mediaserver 级联的时候会有一些问题, 因为多个流通过在媒体服务器级联的时候会有相同的ip, 这种情况下只能通过ssrc来区分不同的音视频流, 这种情况下个需要保证ssrc不能冲突.
我在https://github.com/notedit/media-server-go 这个项目中, 暴露除了服务端单端口的api, 具体可以看这里https://github.com/notedit/media-server-go/blob/master/endpoint.go#L34,
同时通过ssrc自增的方式做了ssrc的防冲突, 在服务端级联的时候也可以放心的使用单端口, 感兴趣的可以研究下.
我的github地址 https://github.com/notedit