WebRtc以Trickle ICE形式去进行pair
文章目录
- 简介
- 时序图
- 伪代码
- 主动方
- 被动方
简介
Trickle ICE(Interactive Connectivity Establishment)是WebRTC的一种流程,它允许WebRTC应用程序在建立对等连接时逐步收集和交换候选地址。
在Trickle ICE流程中,每个对等端都可以向对等端发送候选地址,而不必等待它们收集所有地址,这可以加快连接建立的过程。相比之下,非逐步收集地址的方法被称为完全收集ICE。
时序图
Offer
v=0
o=- 8532455066844539463 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=extmap-allow-mixed
a=msid-semantic: WMS
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=ice-ufrag:VBzV
a=ice-pwd:nTT/XKze1wW96yfd+BGhtMZ+
a=ice-options:trickle
a=fingerprint:sha-256 A6:2E:0A:C4:C8:18:EC:6F:7B:EB:44:E1:C8:FA:1C:DE:AB:30:40:16:E4:AF:28:2F:D2:D9:EF:DD:1C:38:3B:D1
a=setup:actpass
a=mid:0
a=sctp-port:5000
a=max-message-size:262144
Answer
v=0
o=- 4045597616857155182 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=extmap-allow-mixed
a=msid-semantic: WMS
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=ice-ufrag:UagN
a=ice-pwd:+vdRuG5iYxr9R6qkeC5XlvDf
a=ice-options:trickle
a=fingerprint:sha-256 8A:76:A2:2B:6D:CD:4C:78:83:C9:89:05:17:A9:2B:E4:7B:05:61:CD:40:82:F9:B3:45:AA:F0:84:EB:25:2D:A9
a=setup:active
a=mid:0
a=sctp-port:5000
a=max-message-size:262144
offer candidate
{"candidate": "candidate:3173800074 1 udp 2113937151 1eb6cf6d-138c-4aa9-8278-17bb8ca982ab.local 63728 typ host generation 0 ufrag VBzV network-cost 999","sdpMLineIndex": 0,"sdpMid": "0"
}
answer candidate
{"candidate": "candidate:3335541002 1 udp 2113937151 fffaa1d8-ea20-49f7-a65b-bd9508d87268.local 50242 typ host generation 0 ufrag UagN network-cost 999","sdpMLineIndex": 0,"sdpMid": "0"
}
伪代码
主动方
第一个阶段 创建Offer和搜集candidate
// 1. 创建peerconnecttion
const peerConnection = new RTCPeerConnection(config);
// 创建datachannel,必须要这个或者用media,否则后面不会搜集candidate
const sendChannel = peerConnection.createDataChannel('sendDataChannel',dcConfig);
// sendChannel.binaryType = 'arraybuffer'; // 可选
sendChannel.addEventListener('open', onSendChannelStateChange);
sendChannel.addEventListener('close', onSendChannelStateChange);
sendChannel.addEventListener('error', onError);
sendChannel.onmessage = onReceiveMessageCallback;
// 2. 创建offer获取des SDP
peerConnection .createOffer().then(gotDes, // 获取描述onCreateSessionDescriptionError // 异常处理);function gotDes(desc) {// 3. 把获取到的des的sdp 发送给远端 类型type = 'offer'websocket.send({type: 'offer', sdp: offer.sdp}) // 4. 在获取DEC SDP后,开始搜集 candidatepeerConnection.setLocalDescription(desc);
}// 4. 监听搜集的candidate
peerConnection.onicecandidate = e => {// 搜集一条/全部 完成后通过信令服务器发送给远端。if (event.candidate) {console.log('iceCandidate', JSON.stringify(event.candidate));websocket.send((JSON.stringify({type: 'candidate',candidate: {candidate: event.candidate.candidate,sdpMLineIndex: event.candidate.sdpMLineIndex,sdpMid: event.candidate.sdpMid}}));}
};
第二阶段 验证answerSDP和candidate
function handleAnswer(data) {if (data.candidate) {pc.addIceCandidate(data.candidate).then(() => {console.log("addIceCandidate success")}).catch(err => {console.log("addIceCandidate error", err)})}if (data.sdp) {pc.setRemoteDescription(data).then(() => {console.log('setRemoteDescription success')}).catch(err => {console.log('setRemoteDescription error')})}
}
被动方
处理OfferSDP和candidate
// 1.创建peerconnection
const peerConnection = new RTCPeerConnection(config);
// 监听datachannel事件
let receiveChannel ;
peerConnection.addEventListener('datachannel', receiveChannelCallback);// 2.处理OfferSDP和candidate
function handleOffer(data) {if (data.candidate) {pc.addIceCandidate(data.candidate).then(() => {console.log("addIceCandidate success")}).catch(err => {console.log("addIceCandidate error", err)})}if (data.sdp) {pc.setRemoteDescription(data).then(() => {// 3.创建answercreateAnswer()}).catch(err => {console.log('createAnswer error', err)})}
}// 4. 监听搜集的candidate
peerConnection.onicecandidate = e => {// 搜集一条/全部 完成后通过信令服务器发送给远端。if (event.candidate) {console.log('iceCandidate', JSON.stringify(event.candidate));websocket.send((JSON.stringify({type: 'candidate',candidate: {candidate: event.candidate.candidate,sdpMLineIndex: event.candidate.sdpMLineIndex,sdpMid: event.candidate.sdpMid}}));}
};function createAnswer() {console.log('createAnswer start')pc.createAnswer(this.answerOptions).then(answer => {console.log('answer sdp: ', JSON.stringify(answer))const sendAnswer = () => {html(JSON.stringify({type: answer.type,sdp: answer.sdp}))}const onSuccess = () => {console.log('createAnswer success')sendAnswer();}const onError = err => {console.log('createAnswer error', err)}pc.setLocalDescription(answer).then(onSuccess).catch(onError)}).catch(err => {console.log('createAnswer error', err)})
}function receiveChannelCallback(event) {receiveChannel = event.channel;receiveChannel.binaryType = 'arraybuffer'; // 可选receiveChannel.onmessage = onReceiveMessageCallback;receiveChannel.onopen = onReceiveChannelStateChange;receiveChannel.onclose = onReceiveChannelStateChange;
}
WebRtc以Trickle ICE形式去进行pair相关推荐
- webrtc 之 sip trickle ice
本文原创自 http://blog.csdn.net/voipmaker 转载注明出处. webrtc 客户端建立通话的过程中通过交互 candidate实现nat穿越,如果这些交互的candida ...
- WebRTC Trickle ICE 策略
什么是Trickle ICE? 在实际使用的过程中,ICE技术存在一个问题,那就是呼叫建立连接很慢,这其中的原因是ICE协商的过程耗费了很多时间.客户端在发起呼叫时先会和STUN服务器通信,从STUN ...
- trickle ICE文档翻译 [draft-rescorla-mmusic-ice-trickle-01.txt]
概括 这文档描述的是ICE扩展,ICE循序渐进的发送或者接受候选列表,而不是等待候选列表交换完成才开始.通过这样配置,ICE在采集候选列表的时候同时进行连接检查,这样大大缩短了完成ICE过程的时间. ...
- webrtc进阶-信令篇-之三:信令、stun、turn、ice
webRTC支持点对点通讯,但是webRTC仍然需要服务端: . 协调通讯过程中客户端之间需要交换元数据, 如一个客户端找到另一个客户端以及通知另一个客户端开始通讯. . 需要处理NAT(网 ...
- webrtc进阶-信令篇-之三:信令、stun、turn、ice 【转】
文章来源:webrtc进阶-信令篇-之三:信令.stun.turn.ice webRTC支持点对点通讯,但是webRTC仍然需要服务端: . 协调通讯过程中客户端之间需要交换元数据, 如一个客 ...
- WebRTC通话原理(六)
WebRTC通话原理-基本流程 基本流程 WebRTC通话最典型的应用场景就是一对一音视频通话,如微信或QQ音视频聊天.通话的过程是比较复杂的,这里我们简化这个流程,把最主要的步骤提取出来,如图所示. ...
- 流媒体学习-WebRTC全面入门学习-1
一.初始WebRTC 1.WebRTC 就是音视频处理+即时通讯的开源库 音视频处理中ffmpeg和WebRTC是两个很重要的一部分,ffmpeg注重与数据音视频的编解码,文件的后处理.WebRTC整 ...
- 【复】基于 WebRTC 的音视频在线监考模块的设计与实现(上)
文章目录 前言 什么是 WebRTC? WebRTC 架构 WebRTC 通讯内容 WebRTC 通讯协议 WebRTC 连接建立过程 后记 前言 最近在做关于考试系统的项目,其中有一项需求分析是要做 ...
- webRTC实战总结
前言 前段时间一直在忙一个基于WebRTC的PC和移动端双向视频的项目.第一次接触webRTC,难免遇到了许多问题,比如:webRTC移动端兼容性检测,如何配置MediaStreamConstrain ...
最新文章
- android资源替换方案overlay,Android 运行时资源替换----Runtime Resource Overlay
- python docker自动化_自动化 – 自动创建docker容器并启动python脚本
- RedisRDB持久化机制
- 同步器之Exchanger
- NEWS - InstallShield 2015 正式发布
- [jQuery基础] jQuery案例 -- 新浪微博
- 异常处理--“System.BadImageFormatException”类型的未经处理的异常在 DataTest.exe 中发生
- 【java笔记】线程(3):Thread类的常用方法
- 《算法导论》第十四章----数据结构的扩张(动态顺序统计)
- java 整数相乘_Java中两个int相乘的结果是怎么算的?
- 线性代数及其应用(原书第5版)
- HikariCP配置手册
- 零基础英语语法速成(一)
- h5+app Android上架华为应用市场被拒原因“拒绝获取手机权限后app会闪退“以及隐私政策问题
- Statistical Analysis:关联度分析之灰色关联分析软件
- 不成熟的男人的爱情观——知乎上另一个关于不成熟男人的见解
- 那些年我们追过的源码
- 词霸的每日一句的api接口
- 考研:研究生考试(十五天学完)之《高等数学上/下册》研究生学霸重点知识点总结之考试内容各科占比及常考知识重点梳理(函数极限连续、一元/多元函数微分学/积分学、常微分函数、向量代数与空间几何、无穷级数)
- java随机生成标点符号_java去除空格、标点符号的方法实例
热门文章
- time_t、SYSTEMTIME、CTime、COleDateTime互转
- 向量 模(module) 范数(norm)
- C#--使用Process类kill进程
- oracle 字符串分割成数组_oracle 中如何分割字符串成为数组?
- DD-路径图、MM-路径图的定义与区别联系
- 阿里云轻量服务器windows系统远程桌面无法连接?
- Git学习之旅--撤销与删除
- pandas数据排序sort_values后面inplace=True与inplace=False的实例驱动理解
- 已有Android工程集成DCloud页面
- 【SSLGZ 2134】猫猫的小鱼