webrtc janus服务器部署在公网,coturn转发媒体流

news2024/12/26 21:16:23

janus本身部署在公网时,其内部使用的libnice库已经实现了stun的功能,在配置文件janus.jcfg里面,nat_1_1_mapping配置成公网地址,其位于NAT后面的局域网客户端之间可以实现媒体流之间的分享,发布者将媒体流推到公网,而janus服务端将媒体流推给订阅者。

如下图所示:
在这里插入图片描述

这种情况下,根本不需要coturn,现在引入coturn,coturn是stun和turn的结合体,其中stun用于发现地址发现,turn用于流转发。
关于coturn,看到的博客都是用于地址发现,如下图这样一个场景,收集candidate。
在这里插入图片描述

而对于流转发,尚未找到合适的博客。
本篇博客,主要说明coturn的流转发功能。

首先,本人在公网上部署了coturn,关于部署的过程,本人参考了博客
coturn服务配置
其中在turnserver.conf的最后,本人添加了如下内容:

listening-port=19302
listening-ip=0.0.0.0
external-ip=xxx.xxx.251.92
min-port=20000
max-port=40000
user=li:li123
realm=stun.XX.cn
cli-password=qwerty
cert=/usr/local/turnserver/etc/turn_server_cert.pem
pkey=/usr/local/turnserver/etc/turn_server_pkey.pem

其中external-ip是公网地址,为了隐私,本人将ip段的前面部分用xxx.xxx代替。

然后用下面命令启动coturn服务

./bin/turnserver -v -r xxx.xxx.251.92 -a -o -c ./etc/turnserver.conf

启动服务后,发现19302既是tcp端口,又是udp端口。

下面我们将NAT内的客户端的流经过coturn转发,推给janus服务端,下面分别给出地址信息:
coturn:公网地址为xxx.xxx.251.92(中国 天津市),本地地址为10.0.0.143
janus:公网地址为xxx.xxx.251.90(中国 天津市),本地地址为10.0.0.122

客户端地址:本地地址10.0.0.2,所在NAT:60.12.13.106(中国 浙江省 杭州市 滨江区)

注意,客户端的本地地址和上面的coturn以及janus的本地地址不能互通。

此时媒体发布者的流走向如下:
在这里插入图片描述

媒体订阅端走向为:
在这里插入图片描述

下面我们讲解下媒体发布情况下,终端将流推经过coturn转发推给janus的过程。

首先,janus的配置文件中,nat_1_1_mapping注释掉,关于turn的配置开启,如下图所示:
在这里插入图片描述
其中公网地址的前部分做了马赛克处理,turn_user和turn_pwd按照配置coturn时设置的信息来,不要配错。

同时webrtc客户端也需要将coturn的地址加入进来,代码如下:
在这里插入图片描述
关于客户端为何需要将coturn的地址添加进去,后面再做解释。

然后启动客户端,加入会议,接着在客户端所在机器,coturn所在机器,janus所在机器,开启抓包,然后打开摄像头,向服务端推流,结果发现,流直接推给了janus,没有经过coturn。

我查看了在sdp交互时,janus回给客户端的answer sdp,如下所示:

o=- 2743266240368598531 2 IN IP4 10.0.0.122
s=VideoRoom 38584232
t=0 0
a=group:BUNDLE video
a=msid-semantic: WMS janus
m=video 9 UDP/TLS/RTP/SAVPF 127 120
c=IN IP4 10.0.0.122
b=AS:4096
a=recvonly
a=mid:video
a=rtcp-mux
a=ice-ufrag:/6At
a=ice-pwd:V0LKmCsUWBaXjcAFKkHmqK
a=ice-options:trickle
a=fingerprint:sha-256 D2:B9:31:8F:DF:24:D8:0E:ED:D2:EF:25:9E:AF:6F:B8:34:AE:53:9C:E6:F3:8F:F2:64:15:FA:E8:7F:53:2D:38
a=setup:active
a=rtpmap:127 H264/90000
a=fmtp:127 profile-level-id=42e01f;packetization-mode=1
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=extmap:3 urn:3gpp:video-orientation
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=rtpmap:120 rtx/90000
a=fmtp:120 apt=127
a=ssrc-group:FID 3739256708 2784241827
a=candidate:1 1 udp 2015363327 10.0.0.122 32893 typ host
a=candidate:2 1 udp 1679819007 xxx.xxx.251.90 32893 typ srflx raddr 10.0.0.122 rport 32893
a=candidate:3 1 udp 505413887 xxx.xxx.251.92 27192 typ relay raddr 10.0.0.122 rport 32893
a=end-of-candidates

注意,公网地址处,本人用了xxx代替。

可见answer sdp的最后部分是3个candidate,其中第一个是janus的本地地址,第二个是janus的公网地址(srflx反射地址),第三个是janus的relay地址(coturn地址)。
而本人其实在janus上并没有配置janus的公网ip,janus通过函数nice_agent_set_relay_info设置了coturn信息,其通过与coturn的交互得知了自己的公网ip,如下图所示,janus在向coturn进行relay端口请求时,得到了自己的公网ip。
在这里插入图片描述
而candidate是有优先级的,srflx的优先级要高于relay,故此次推流,发现没有经过coturn,直接发给了janus。

由于answer sdp中的candidate是janus组装的,故可以修改janus的代码,将srflx的地址去掉,在ice.c的函数janus_ice_candidates_to_sdp里面,添加红色部分的代码,将srflx的candidate屏蔽掉。
在这里插入图片描述

重新编译并启动janus,启动客户端并发布媒体,janus回复的answer sdp如下:

o=- 2892261328926992312 2 IN IP4 10.0.0.122
s=VideoRoom 95364800
t=0 0
a=group:BUNDLE video
a=msid-semantic: WMS janus
m=video 9 UDP/TLS/RTP/SAVPF 127 120
c=IN IP4 10.0.0.122
b=AS:4096
a=recvonly
a=mid:video
a=rtcp-mux
a=ice-ufrag:3GO5
a=ice-pwd:mjai24kvf9SI1+fE3IXIg4
a=ice-options:trickle
a=fingerprint:sha-256 D2:B9:31:8F:DF:24:D8:0E:ED:D2:EF:25:9E:AF:6F:B8:34:AE:53:9C:E6:F3:8F:F2:64:15:FA:E8:7F:53:2D:38
a=setup:active
a=rtpmap:127 H264/90000
a=fmtp:127 profile-level-id=42e01f;packetization-mode=1
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=extmap:3 urn:3gpp:video-orientation
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=rtpmap:120 rtx/90000
a=fmtp:120 apt=127
a=ssrc-group:FID 2148634348 4202343640
a=candidate:1 1 udp 2015363327 10.0.0.122 22349 typ host
a=candidate:3 1 udp 505413887 xxx.xxx.251.92 24104 typ relay raddr 10.0.0.122 rport 22349
a=end-of-candidates

看sdp最后部分的candidate,只剩下了两个,这次经过抓包分析,流确实由客户端推给coturn,然后由coturn推给janus。

下面我根据三个抓包分析下过程,先分析下客户端的流如何发给coturn,首先从sdp中看到xxx.xxx.251.92 24104,这个是coturn用于接收客户端流的地址端口,这个24104端口是由janus向coturn申请转发端口时,coturn主机上分配的。

客户端将流发给coturn时,在NAT上进行了打洞,打出的地址为(60.12.13.106:21003),下面是抓包的过程,本人直接用文本写出来,避免贴图模糊。

10.0.0.2(61888)--------Binding Request user:3G05:y04Z--------------> xxx.xxx.251.92(24104)
10.0.0.2(61888)<-Binding Success Response XOR-MAPPED-ADDRESS: 60.12.13.106:21003 user: 3GO5:yO4Z--xxx.xxx.251.92(24104)

下面抓包下janus向coturn申请转发端口(端口号:24104)的过程

10.0.0.122(22349)--------Allocate Request UDP----------->xxx.xxx.251.92(19302)
10.0.0.122(22349)<--------Allocate Error Response error-code: 401 (Unauthenticated) Unauthorized with nonce realm: xxx.xxx.251.92-----------xxx.xxx.251.92(19302)	
10.0.0.122(22349)--------Allocate Request UDP realm: xxx.xxx.251.92 with nonce user: li----------->xxx.xxx.251.92(19302)
10.0.0.122(22349)<--------Allocate Success Response XOR-RELAYED-ADDRESS: xxx.xxx.251.92:24104 XOR-MAPPED-ADDRESS: xxx.xxx.251.90:22349 lifetime: 600-----------xxx.xxx.251.92(19302)

交互中,可以发现,向 coturn申请转发端口,需要用户名和密码,由交互过程中的第四步发现,coturn分配了24104的转发端口,在coturn的24104端口接收到了客户端的媒体流后,其用19302端口将媒体流发给了janus的22349端口(不是24104端口)。

10.0.0.143(19302)--------UDP媒体流----------->xxx.xxx.251.90(22349)

janus在申请转发端口时,就已经给出了其本身接收转发流的端口22349。

下面说下webrtc客户端为何需要将coturn的地址加入进来,若不将coturn的地址加入进来,发现,客户端在向coturn转发端口24104 打洞(Binding Request)的时候,此端口一直未能给以回复,导致打洞失败,具体原因未知。

经过抓包发现,客户端 打洞(Binding Request)的时候,必须先向coturn的配置端口19302进行Binding请求,然后才能向此转发端口(24104)进行Binding,交互如下:

10.0.0.2(61888)--------Binding Request--------------> xxx.xxx.251.92(19302)
10.0.0.2(61888)<-Binding Success Response XOR-MAPPED-ADDRESS: 60.12.13.106:21002 MAPPED-ADDRESS: 60.12.13.106:21002 RESPONSE-ORIGIN: xxx.xxx.251.92:19302--xxx.xxx.251.92(19302)
10.0.0.2(61888)--------Binding Request user:3G05:y04Z--------------> xxx.xxx.251.92(24104)
10.0.0.2(61888)<-Binding Success Response XOR-MAPPED-ADDRESS: 60.12.13.106:21003 user: 3GO5:yO4Z--xxx.xxx.251.92(24104)

客户端代码将coturn的地址加入进来,会触发向coturn的配置端口19302进行Binding请求,使得最后打洞成功。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/445322.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【网络】-- https协议

目录 http协议 https协议 安全 概念 什么是"加密"&#xff1f; 为什么要加密&#xff1f; 常见的加密方式 对称加密 非对称加密 数据摘要 && 数据指纹 数字签名 HTTPS 的工作过程探究 方案一&#xff1a;只使用对称加密 方案二&#xff1a;只使…

深眸科技|制造行业升级速度加快,2D视觉与3D视觉该如何选择?

随着人工智能的不断发展&#xff0c;机器视觉已经成为当下最炙手可热的技术之一。在制造业转型升级并且迅猛发展的过程中&#xff0c;对于产品的高精度、零缺陷的需求也在不断提升&#xff0c;而机器视觉的出现为制造业产业升级提供了强有力的驱动力。 随着5G、AI等技术的不断…

174_技巧_Power BI 动态格式(万|亿)

174_技巧_Power BI 动态格式(万|亿) 一、背景 Power BI 2023年4月份更新&#xff0c;新增加了一个预览功能&#xff1a;动态格式(Dynamic format strings for measures)&#xff0c;度量值的结果可以动态的显示为不同的格式。 今天我们主要来看一个技巧&#xff0c;如何在 P…

[架构之路-171]-《软考-系统分析师》-5-数据库系统-1- 数 据 库 的 控 制 功 能(并发控制、性能优化)

目录 5 . 4 数 据 库 的 控 制 功 能 5.4.1 并发控制 1 . 事务的基本概念 2 . 数据不一致问题 3 . 封锁协议 4 . 死锁问题 5.4.2 数据库性能优化 1 . 硬件升级 2 . 数据库设计 5.4.3 数据库的完整性 1 . 完整性约束条件 2 . 实体完整性 3 . 参照完整性 4 . 用户定…

华为云-使用脚本初始化Linux数据盘

操作场景 本文以云服务器的操作系统为“CentOS 7.4 64位”为例&#xff0c;采用初始化数据盘脚本的方式为数据盘设置分区。 不同云服务器的操作系统的格式化操作可能不同&#xff0c;本文仅供参考。 须知&#xff1a; 首次使用磁盘时&#xff0c;如果您未参考本章节对磁盘执…

json for modern c++

目录 json for modern c概述编译问题问题描述问题解决 读取JSON文件demo json for modern c GitHub - nlohmann/json: JSON for Modern C 概述 json for modern c是一个德国大牛nlohmann写的&#xff0c;该版本的json有以下特点&#xff1a; 1.直观的语法。 2.整个代码由一个…

QT 创建插件 CTK开发(三)

CTK 为支持生物医学图像计算的公共开发包,其全称为 Common Toolkit。为医学成像提供一组统一的基本功能;促进代码和数据的交互及结合;避免重复开发;在工具包(医学成像)范围内不断扩展到新任务,而不会增加现有任务的负担;整合并适应成功的解决方案。 本专栏文章较为全面…

DP4056国产兼容替代LTC40561A锂离子电池充电芯片

目录 锂电池 VS 锂离子电池DP4056简介DP4056芯片特性 锂电池 VS 锂离子电池 锂电池是以锂金属或锂合金为正极材料&#xff0c;使用非水电解质溶液的电池。锂电池与锂离子电池不一样的是&#xff0c;前者是一次电池&#xff0c;后者是充电电池。锂离子电池工作原理就是依靠锂离…

(大数据开发随笔6)Hadoop 3.3.x分布式环境部署——本地模式

本地模式 材料准备 Linux虚拟机-CentOS7hadoop-3.3.1.tar.gz Index of /hadoop/common (apache.org)jdk-8u321-linux-x64.tar.gz Java Archive | Oracle Centos7虚拟机部署 准备材料&#xff1a; VMware17CentOS-7-x86_64-Minimal-2009.iso centos-7-isos-x86_64安装包下载…

2022国赛34:路由器之间ISIS协议配置

大赛试题内容: 5.RT1以太链路、RT2以太链路之间运行ISIS协议,进程10,分别实现loopback3 之间ipv4互通和ipv6互通。RT1、RT2的NET分别为10.0000.0000.0001.00、10.0000.0000.0002.00,路由器类型是Level-2,接口网络类型为点到点。配置域md5认证和接口md5认证,密码均为Key…

企业如何从0到1落地BI项目

企业需要数据整合、分析展现及应用的完整数据平台方案。为了满足集团化BI建设需求&#xff0c;企业决策层需要基于全局数据进行分析&#xff0c;需要提供数据整合、存储、计算到数据应用的端到端数据平台。 商业智能BI - 派可数据BI可视化分析平台 BI的实践落地需要全生命周期…

[Python基础] 序列(列表/元组)和字典的操作详解

文章目录 序列概念序列列表列表的创建和下标访问创建下标 列表的切片操作列表的遍历列表的插入操作列表的查找和删除列表的拼接 元组元组的相关操作 字典概念字典的创建查找字典中的key&#xff0c;value字典的增删改字典的遍历 序列概念 包含若干个元素, 元素有序排列, 可以通…

APIs -- DOM节点操作

1. 日期对象 日期对象&#xff1a;用来表示时间的对象 作用&#xff1a;可以得到当前系统时间 1.1 实例化 在代码中发现了new关键字时&#xff0c;一般将这个操作称为实例化 创建一个时间对象并获取时间&#xff1a;const date new Date(); // 实例化 new// 1.得到当前时…

React语法(N)

文章目录 React简介概述官网特点生态 react学习的说明新的官网全力投入现代React与Hooks React脚手架create-react-app官网创建和启动项目项目结构sass支持 Vite创建和启动项目项目结构常见配置 虚拟DOM什么是虚拟DOM虚拟DOM优缺点优点&#xff1a;缺点&#xff1a; 虚拟DOM实现…

CTF之命令执行常见绕过

命令执行常见绕过 1.空格代替 当我们执行系统命令时&#xff0c;不免会遇到空格&#xff0c;如cat flag.txt&#xff0c;当空格被程序过滤时&#xff0c;便需要利用以下字符尝试代替绕过&#xff1a; < ${IFS} $IFS$9 %09测试如下&#xff1a; $IFS 在 linux 下表示分隔…

增长黑武器|LTD荣获“2023中国工业数字化赋能奖先锋”

​ 2014年&#xff0c;北京 2015年&#xff0c;南昌 2016年&#xff0c;上海 ...... 2022年&#xff0c;南京 2023年&#xff0c;4月21日 由中国生产力促进中心协会数字经济工作委员会提供指导&#xff0c;由托比网主办的“第六届中国工业数字化高峰论坛”在上海举行。本…

力扣sql中等篇练习(十)

力扣sql中等篇练习(十) 1 查询回答率最高的问题 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # count(具体字段)会自动不统计null值 SELECT t1.question_id survey_log FROM (SELECT question_id,count(answer_id)/count(*) rFROM SurveyLogGROUP…

STM32常用的开发工具有哪些

这么多工具&#xff0c;选择困难啊&#xff0c;先列出来&#xff0c;以后有选择了给大家说&#xff0c;对了&#xff0c;2023年还有一个新玩法就是VSCode 本文为大家汇总 STM32 常用的一些开发工具。 IDE&#xff08;集成开发环境&#xff09; IDE&#xff1a;IntegratedDeve…

springboot_模拟01

demo 模拟springboot pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.…

李沐读论文笔记--大模型时代下做科研的四个思路

大模型时代下做科研的四个思路 0. 视频来源&#xff1a;1. 提高效率&#xff08;更快更小&#xff09;1.1 PEFT介绍(parameter efficient fine tuning)1.2 作者的方法1.3 AIM效果1.3.1AIM 在 K400 数据集上的表现1.3.2AIM 在 Something-Something 数据集、K700 数据集和 Diving…