基于webrtc的数据传输研究总结

news2025/7/27 11:56:23

什么是webrtc

WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。

一个简单的例子 PyWebRTC

这里简单介绍一个例子。在这个例子中,建立WebRTC连接的过程如下图所示:
在这里插入图片描述
这是一个简单基于python实现的服务端响应用户请求的例子。当客户端(Client)发起请求,服务器端(Server)与Client建立WebRTC连接,并把流媒体资源库中的demo-instruct.wav音频通过WebRTC连接的方式传输到Client,在Client这一端可以实时听到音频的播放。

RTCPeerConnection

webrtc的P2P连接依赖于实现在两端主体程序中的RTCPeerConnection对象(pc_client和pc_server),它们需要经历两个阶段的协商,才能建立连接。

媒体协商

媒体协商要做的事情,是让彼此了解对方的多媒体能力(上图中红色标记的步骤)。例如:webrtc默认使用V8编码和解码,如果Client不支持V8解码,如果没有媒体协商过程,那么即便是连接成功,Server把视频数据发给Client,对方也无法播放。进一步,如果Client支持VP8、H264多中编码格式,而Server支持VP9、H264,如果要保证两端的正常的编码、解码,最简单的办法是取它们的交集,H264。

媒体协商的过程在代码层实际上是交换了各自的sdp信息,这个过程也叫 offer/answer 过程(可能是因为Client端的sdp信息由createOffer()方法创建,而Server的sdp信息由createAnswer()方法创建)。在这个例子中,这个过程大致为,首先由Client通过普通http请求的方式将自身sdp信息Post给Server,然后Server将自身sdp信息作为响应返回给Client,它们各自使用以下语句,来设置自身的sdp,和对方的sdp。

#用于设置自身的多媒体特征sdp
pc.setLocalDescription()
#用于设置对方的多媒体特征sdp
pc.setRemoteDescription

sdp的具体格式可以分成三个部分,*号表示的是可选的。如下:

Session description
    v=  (protocol version)
    o=  (originator and session identifier)
    s=  (session name)
    i=* (session information)
    u=* (URI of description)
    e=* (email address)
    p=* (phone number)
    c=* (connection information -- not required if included in all media)
    b=* (zero or more bandwidth information lines)
    [...One or more time descriptions ("t=" and "r=" lines)]
    z=* (time zone adjustments)
    k=* (encryption key)
    a=* (zero or more session attribute lines)
    [...Zero or more media descriptions]

Time description
    t=  (time the session is active)
    r=* (zero or more repeat times)

Media description, if present
    m=  (media name and transport address)
    i=* (media title)
    c=* (connection information -- optional if included at session level)
    b=* (zero or more bandwidth information lines)
    k=* (encryption key)
    a=* (zero or more media attribute lines)

举例如下:

v=0
o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5
s=SDP Seminar
i=A Seminar on the session description protocol
u=[http://www.example.com/seminars/sdp.pdf](http://www.example.com/seminars/sdp.pdf)
[e](mailto:e=j.doe@example.com)[=j.doe@example.com](mailto:e=j.doe@example.com) (Jane Doe)
c=IN IP4 224.2.17.12/127
t=2873397496 2873404696
a=recvonly
m=audio 49170 RTP/AVP 0
m=video 51372 RTP/AVP 99
a=rtpmap:99 h263-1998/90000

网络协商

当各端调用 setLocalDescription 后,WebRTC就开始建立网络连接,主要包括收集candidate、交换candidate和按优先级尝试连接,该过程被称为ICE(Interactive Connectivity Establishment,交互式连接建立)。其中每个 candidate 都包含IP地址、端口、传输协议、类型等信息。
根据 RFC5245 协议 ,WebRTC将 candidate分为了四个类型:host、srflx、prflx、relay,它们的优先级依次降低。
host:Host Candidate,根据主机的网卡数量决定,一般一个网卡对应一个ip地址,然后给每个ip随机分配一个端口生成。
srflx:Server Reflexive Candidate,根据STUN服务器获得的ip和端口生成。
prflx:Peer Reflexive Candidate,根据对端的ip和端口生成。
relay:Relayed Candidate,根据TURN服务器获得的ip和端口生成。
简单点来说,candidate的交换即告诉对方自己传输数据的方式。在PyWebRTC的这个例子中,candidate的交换是自动完成的。不需要额外编写代码。

以下是当Client和Server在同一个网段下,没有使用turnserver时的candidate信息

在offer中的candidate信息

a=candidate:3508291585 1 udp 2122260223 192.168.36.1 62937 typ host generation 0 network-id 1
a=candidate:3773578447 1 udp 2122194687 172.16.123.63 62938 typ host generation 0 network-id 2
a=candidate:2678043889 1 tcp 1518280447 192.168.36.1 9 typ host tcptype active generation 0 network-id 1
a=candidate:2926559295 1 tcp 1518214911 172.16.123.63 9 typ host tcptype active generation 0 network-id 2

在answer中的candidate信息

a=candidate:ae131dace505164676d6f637ba6d2232 1 udp 2130706431 172.16.123.63 62943 typ host
a=candidate:4f58facbc6fb04d2f88caee9bdc8c3c6 1 udp 2130706431 192.168.36.1 62944 typ host
a=candidate:c23b409001556fce7bcd691e8a5c284f 1 udp 1694498815 113.67.225.115 10944 typ srflx raddr 172.16.123.63 rport 62943

PyWebRTC 与 TurnServer结合的例子

什么是turnserver

在实际情况中,我们更多面临由基于NAT所搭建的网络环境。NAT的用处主要有两个:
(1)解决IPv4地址不够用的问题,可以让多个主机共用一个公网IP。
(2)将主机隐藏在内网中,外网比较难访问到真实主机。
在这种情况下,基于webrtc的Client和Server无法建立对等连接,所以需要依赖turnserver的中继功能来转发,以解决处在不同网络域对等端的连接建立与通讯问题。

使用VMWare和Docker模拟内外网环境

由于缺乏真实的Nat内外网环境,这里使用了两套虚拟网络机制来模拟内外网环境,这里记录一下搭建这套环境的过程。首先安装一个虚拟机(Ubuntu20.04),网络连接选择桥接模式,并且是自动获取ip。
在这里插入图片描述
这种模式下给虚拟机分配的ip会与宿主机(相对于虚拟机)处于同一网段,例如我当前宿主机(相对于虚拟机)的ip为172.16.123.63,而虚拟机的ip为172.16.123.118。这样就会形成一个“外网环境”,并且Client运行在外网环境中浏览器中。

在虚拟机中安装docker,利用docker虚拟网络模拟内网环境。注意创建容器时network_mode不能为host,因为这样将无法控制端口的开放,而在实际情况中,端口默认都是不开放的。创建容器时,docker会默认生成一个虚拟桥接网卡(使用ifconfig可以看到),这个网络与容器里查询到的ip处于一个网段。这样形成了一个“内网环境”。
在这里插入图片描述
如上图所示,在虚拟机中ifconfig查看网络可知,ens33是VMWare的虚拟网卡,br-7261d1118a42是它所安装的docker的其中一个虚拟网卡,可通过docker network ls 查看docker的所有虚拟网卡,如下图所示,这串数字与br-7261d1118a42对应
在这里插入图片描述
进去容器中查看它的ip,如下图所示,可以知道容器ip与虚拟机的虚拟网卡ip在统一网段。
在这里插入图片描述
最后总结,利用VMWare和Docker两套虚拟网络机制模拟的内外网网络环境可以用以下示意图来表示
在这里插入图片描述

创建Server和coturn的镜像并创建容器

由于Server和coturn部署在虚拟内网,而内网由docker模拟,所以Server和coturn需要制作成镜像。

FROM python:3
WORKDIR /usr/src/app
COPY pywebrtc ./
COPY turnserver.conf ./
COPY requirements.txt ./
COPY sources.list ./
RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak \
  && cp ./sources.list /etc/apt/sources.list \
  && apt-get update \
  && apt-get install coturn -y \
  && apt-get install vim -y \
  && apt-get install net-tools \
  && pip install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple \
  #&& openssl req -x509 -newkey rsa:2048 -keyout /etc/sslkey.pem -out /etc/sslcert.pem -days 99999 -nodes \
  && mv /etc/turnserver.conf /etc/turnserver.conf.bak \
  && cp turnserver.conf /etc/turnserver.conf \
  && rm /usr/src/app/turnserver.conf \
  && turnadmin -a -u demo -p 4080218913 -r 172.16.123.118 \
  && turnadmin -l
EXPOSE 8801
EXPOSE 3478
EXPOSE 3478/udp
EXPOSE 9000
EXPOSE 9000/udp
EXPOSE 59000-59010/udp
CMD [ "python", "main.py" ]

如上DockerFile所示,内容包括:
(1)基础镜像是python:3,因为Server是基于aiortc和tornado实现的python应用。
(2)修改镜像中系统软件源为国内源。
(3)安装coturn,vim,net-tools,安装Server运行所需要的依赖。
(3)替换镜像中coturn的配置文件turnserver.conf
(4)开放相关端口,需要对应turnserver.conf中的端口配置。8801端口用于交换sdp媒体描述信息和icecandidate网络信息(icecandidate可以手动设置);3478是tunserver的监听端口,在Client端指定turnserver地址时会用到。9000也是turnserver的监听端口,在turnserver.conf中对应tls-listening-port,使用这个端口会在TLS & DTLS基础上安全传输;59000-59010是turnserver 启动UDP中继通道的端口上下界。
镜像创建结束后,使用docker-compose.yaml创建容器。

version: '3.1'
services:
  pywebrtcturn:
    image: alan/pywebrtcturn:v1
    container_name: pywebrtcturn
    ports:
      - "8801:8801"
      - "3478:3478"
      - "3478:3478/udp"
      - "9000:9000"
      - "9000:9000/udp"
      - "59000-59010:59000-59010/udp"

    # network_mode: "host"

turnserver的配置和启动

使用docker-compose.yaml创建容器后,进入容器,使用以下命令创建公钥和秘钥

openssl req -x509 -newkey rsa:2048 -keyout /etc/sslkey.pem -out /etc/sslcert.pem -days 99999 -nodes

创建用户,但是在我们的例子里,这一步已在DockerFile里完成,进入容器后可以忽略这一步

turnadmin -a -u demo -p 4080218913 -r 172.16.123.118

设置turnserver的配置,/etc/turnserver.conf,如下所示

listening-ip=172.18.0.2
listening-port=3478
tls-listening-port=9000
relay-ip=172.18.0.2
relay-threads=50
external-ip=172.16.123.118
min-port=59000
max-port=59010
lt-cred-mech
Verbose
fingerprint
cert=/etc/sslcert.pem
pkey=/etc/sslkey.pem
realm=172.16.123.118
no-loopback-peers
no-multicast-peers
mobility
no-clis

这里需要特别注意几个ip的设置,listening-ip、relay-ip和external-ip等等,需要结合上面虚拟内外网网络环境的示意图来对应。几个端口的设置则要结合DockerFile和docker-compose.yaml来设置。

启动turnserver

turnserver

如何使用turnserver

在前端页面作iceserver的配置便可

config.iceServers = [{url: 'turn:172.16.123.118:3478',username:"demo",credential:"4080218913"}];

在页面中点击start,等待一下,便可听到处于虚拟内网中Server返回的多媒体资源。

注意:turnserver有turn和stun两种方式,但是我用stun只成功了一次,我猜测是stun机制下配置中的min-port和max-port并没有生效,中继通道所使用的端口并没有控制在容器创建时预期的59000-59010范围内。

研究总结

我研究webrtc的过程中有几个要点
(1)webrtc p2p通信指的是两侧的RTCPeerConnection对象,但是建立连接时需要帮助它们交换sdp媒体特征描述信息以及icecandidate网络传输信息,这一步可以基于用多种方式来实现。
(2)如何在有限的条件下模拟内外网环境。
(3)turnserver配置要准确,要清楚内网ip和外网ip具体分别指的是什么,要有一定的网络基础。

基于websocket实现的webrtc连接

待更新

webrtc相关概念详细说明

待更新

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

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

相关文章

最新阿里云ECS服务器S6/C6/G6/N4/R6/sn2ne/sn1ne/se1ne处理器CPU性能详解

阿里云ECS服务器S6/C6/G6/N4/R6/sn2ne/sn1ne/se1ne处理器CPU性能怎么样?阿里云服务器优惠活动机型有云服务器S6、计算型C6、通用型G6、内存型R6、云服务器N4、云服务器sn2ne、云服务器sn1ne、云服务器se1ne处理器CPU性能详解及使用场景说明。 1、阿里云服务器活动机…

全局唯一ID

文章目录前言MongoDB ObjectIdTwitter SnowflakeUUID前言 基于数据库设置其实初始值,以及增量步长。基于ZK,Redis,改良雪花集中式服务生成,远程调用获取id。基于并行空间划分,Snowflake(8Byte字节64bit位)&#xff0c…

供应化学试剂mPEG-Azide,mPEG-N3,甲氧基-聚乙二醇-叠氮,CAS:89485-61-0

1、名称 英文:mPEG-Azide,mPEG-N3 中文:甲氧基-聚乙二醇-叠氮 2、CAS编号:89485-61-0 3、所属分类:Azide PEG Methoxy PEG 4、分子量:可定制,甲氧基-聚乙二醇-叠氮 5k、甲氧基-PEG-叠氮 10…

Higress 实战: 30行代码写一个 Wasm Go 插件

前言 在11月15号的直播 《Higress 开源背后的发展历程和上手 Demo 演示》中,为大家演示了 Higress 的 Wasm 插件如何面向 Ingress 资源进行配置生效,本文对当天的 Demo 进行一个回顾,并说明背后的原理机制。 本文中 Demo 运行的前提&#x…

PPOCR车牌定位模型推理后处理优化研究

综述 最近在研究基于PPOCR算法的车牌识别(LPR),部署模型后发现之前关于OCR文本定位的后处理策略在车牌识别中存在定位精度不够高,文本框偏移的问题,如: 经分析发现是之前的OCR后处理策略存在一定局限&am…

java刷题day 03

选择题: 解析: 父类private的成员变量,根据权限修饰符的访问控制范围,只有在类内部才能被访问,就算是他的子类,也不能访问。这里如果将Person p new Child();改成 Person p new Person();代码依然无法通过…

乐趣国学—品读《弟子规》中的“余力学文”之道

文章目录余力学文不力行 但学文 长浮华 成何人但力行 不学文 任己见 昧理真读书法 有三到 心眼口 信皆要方读此 勿慕彼 此未终 彼勿起宽为限 紧用功 工夫到 滞塞通心有疑 随札记 就人问 求确义房室清 墙壁净 几案洁 笔砚正墨磨偏 心不端 字不敬 心先病列典籍 有定处 读看毕 还原…

信号完整性测试,关于SMA装配的细节,很多人都忽视了

作者 | 萧隐君,仿真秀专栏作者 SMA转接头是射频微波、天线和高速电路测试经常用到的一种连接器,应用非常广泛,种类也很多。在信号完整性的测试夹具中,2.92mm的SMA用的较多,它的带宽可以到40GHz,对于25Gbps…

【全网独家,收藏吧】10年全部《信息资源管理》真题整理,第2章 信息化规划与组织

文章目录🔥 11 年 4 月《信息资源管理》真卷选择题名词解释综合分析题🔥 11 年 7 月《信息资源管理》真卷选择题名词解释题简答题⭐ 12 年 4 月《信息资源管理》真卷选择题简答题⭐ 12 年 7 月《信息资源管理》真卷选择题简答题⭐ 13 年 4 月《信息资源管…

计算机网络--- 电子邮件

(一)电子邮件系统的组成 电子邮件是一种异步通信方式,通信时不需要双方同时在场。电子邮件把邮件发送到收件人使用的邮件服务器,并放在其中的收件人邮箱中,收件人可以随时上网到自己使用的邮件服务器进行读取。 一…

补盲激光雷达大爆发,各路产品谁领风骚?

11月伊始车载激光雷达赛道上演了冰火两重天的景象。国外Ouster与Velodyne LiDAR宣布合并以抱团取暖,主打OPA技术的Quanergy甚至股市停牌,一时风声鹤唳,寒意阵阵;而反观国内,禾赛、速腾、亮道相继发布纯固态补盲激光雷达…

龙格-库塔法(Runge-Kutta methods)

非线性的常微分方程通常是难以求出解析解的,只能通过多次迭代求近似的数值解。 龙格-库塔法(Runge-Kutta methods)是用于非线性常微分方程的解的重要的一类隐式或显式迭代法。简写做RK法。 对于任意的Yf(X),假设某点(Xi,Yi)的斜…

固定资产管理系统能帮助企业解决哪些问题?

固定资产管理系统是企业信息化转型中重要的工具之一。固定资产在企业整体资金和运营管理中的占比非同一般,因此企业管理者对固定资产的重视程度也逐渐提升。随着企业固定资产数量和种类的增多、人员的增多,以及分支机构和部门的增多,单纯依靠…

数据安全治理白皮书4.0(附下载link)

数据安全治理白皮书是国内最早的数据安全治理白皮书系列,围绕数据安全治理,“新理论、新技术、新实践”,一次系统汇总、梳理分析与集中呈现,2018年-2021年,已发布1.0/2.0/3.0三个版本,2022年,已…

LeetCode | 循环队列的爱情【恋爱法则——环游世界】

兜兜转转⚪还是你❤✒前言环形队列的概念拓展:生产者与消费者一、题目描述二、思路分析🍑初次遇见她♀【是心动的感觉】🍑阻碍一:队空还是队满不好区分【性格互异】🍑解决方案🍑阻碍二:很难获取…

Git之借助Commitizen规范化提交代码

文章目录一、约定式提交规范1.1 概述1.2 规范1.3 好处二、Commitizen2.1 安装2.2 安装并配置cz-customizable依赖2.2.1 安装依赖2.2.2 配置package.json2.2.3 添加cz-config配置文件2.3 使用2.4 问题一、约定式提交规范 1.1 概述 约定式提交规范是一种基于提交信息的轻量级约…

ES6 入门教程 26 编程风格 26.4 对象 26.5 数组 26.6 函数

ES6 入门教程 ECMAScript 6 入门 作者:阮一峰 本文仅用于学习记录,不存在任何商业用途,如侵删 文章目录ES6 入门教程26 编程风格26.4 对象26.5 数组26.6 函数26 编程风格 26.4 对象 单行定义的对象,最后一个成员不以逗号结尾。多…

流媒体传输 - RTSP 协议

概述 协议简介 RTSP RTSP (Real-Time Stream Protocol) 实时流传输协议是一种基于文本的应用层协议,常被用于 建立的控制媒体流的传输,该协议用于 C/S 模型 , 是一个 基于文本 的协议,用于在客户端和服务器端建立和协商实时流会话。 RTP …

JS语句完全攻略

JavaScript 语言定义了 20 套(或个)语句命令,分别执行不同的操作。 以用途划分,JavaScript 语句可以分为:声明、分支控制、循环控制、流程控制异常处理和其他。 以结构划分,JavaScript 语句又可以分为单句…

【Python】基础知识(语句,函数)

目录Python基础语法接上次的知识点补充顺序语句条件/分支语句语法格式空语句 pass循环语句while 循环For循环continue和break函数语法格式调用函数/使用函数函数参数函数返回值变量作用域函数执行过程链式调用嵌套调用函数递归参数默认值关键字参数写在前面🍎&#…