WebRTC 之点对点连接——浏览器

2023-11-19

WebRTC 的精髓——点对点连接

上一篇文章中,主要讲了浏览器怎样获取用户设备上的视频流,并且显示在 HTML5 <video> 标签中。这一篇文章则是让这一切变得有用起来:把视频流发送到另一位用户的浏览器上。WebRTC 特有的点对点连接,可以让服务器不必中转大量的视频数据,让通讯的速度、私密性得到更好的保障。这是 WebRTC 相对于 WebSocket 等技术最大的优势,也就是它存在的根本。

怎样建立点对点连接

要建立一个点对点连接,并在其上传送视频内容,我们需要两个浏览器互相交换以下信息:

1.视频流的元数据,包括分辨率和编码格式等
2.各自的网络连接情况,包括用于 NAT 穿透的信息

WebRTC 用于实现了以上信息交换,提供给浏览器 JavaScript 平台的 API 就是 RTCPeerConnection

为了完成以上第 1 种信息的交换,我们用 RTCPeerConnection 的 createOffer() 方法生成一个 Offer,它是以 SDP(Session Description Protocol,会话描述协议)格式传送的。对方收到 Offer 后,应该生成一个 Answer 并发回,这个 Answer 同样是 SDP 格式的。通信的双方通过调用setLocalDescription() 方法,把自己生成的 SDP 设置成本地描述;通过调用setRemoteDescription() 方法,把对方发给自己的 SDP 设置成远程描述。以上的这个过程,被统称为JSEP(JavaScript Session Establishment Protocol,JavaScript 会话建立协议)。


JSEP 结构(via html5rocks.com)

对于以上第 2 种信息的交换,则是通过 ICE(Interactive Connectivity Establishment,交互式连接建立)完成的。对于点对点连接最简单的设想是,大家都连接在一个网络中,只要双方都知道对方的 IP 地址,我就可以直接发送数据。但现实永远不会这么简单:如今的网络世界中,绝大部分设备并不是直接连接到互联网上,具有一个公网 IP 地址,而是处在层层的路由器和防火墙的背后,这也就使得直接建立连接变得不可能。不过,如果双方都向一个公网上的服务器发送一个请求,这台服务器可以获取到双方的公网地址,这样就可以让双方知晓怎样和对方进行通讯。这就是 STUN 服务器。


信令交换与 STUN/TURN 服务器(via html5rocks.com)

当双方完成了 Offer 和 Answer 的交换后,RTCPeerConnection 便利用 STUN 服务器收集 ICE 候选,也就是双方建立连接的多个可能途径,然后在这些候选中挑选最优化的一个,用以建立点对点连接。

STUN 还有一个扩展,即 TURN 服务器。除了实现 STUN 的全部功能外,当双方由于某种原因(如防火墙)还是没法建立点对点连接时,TURN 服务器可以起到中转的作用,让双方可以绕过防火墙进行通讯(事实上绝大多数防火墙被配置为允许从内部向外主动发起的连接)。

实例代码

// 建立一个 RTCPeerConnection 实例,这里设置了 STUN 或 TURN 服务器
var servers = {
  'iceServers': [
    {
      'url': 'stun:turn.mywebrtc.com'
    },
    {
      'url': 'turn:turn.mywebrtc.com',
      'credential': 'siEFid93lsd1nF129C4o',
      'username': 'webrtcuser'
    }
  ]
};
peerConnection = new RTCPeerConnection(servers);

// 交换 ICE 候选,通过 WebSocket 发送
peerConnection.onicecandidate = function (e) {
  if (e.candidate) {
    console.log(['ICE candidate', e.candidate]);
    socket.emit('message', roomToken, {
      'candidate': e.candidate
    });
  }
};

// 接收到对方添加的视频流时,显示在本地的 <video> 标签中
peerConnection.onaddstream = function (e) {
  remoteMediaStream = e.stream;
  remoteVideo.src = URL.createObjectURL(remoteMediaStream);
};

// 在这里添加上一篇文章中获取到的本地视频流
peerConnection.addStream(localMediaStream);

// 包装一个 Offer
peerConnection.createOffer(gotLocalDescription, handleError);

// 有了 Offer,通过 WebSocket 发送给对方
function gotLocalDescription(desc) {
  peerConnection.setLocalDescription(desc);
  socket.emit('message', roomToken, {
    'sdp': desc
  });
}

// 在 WebSocket 中接收到信息时
socket.on('message', function (message, socketId) {
if (message.sdp) {
    // 接收到 Offer 时,创建 Answer 并发送
    var desc = new RTCSessionDescription(message.sdp);
    peerConnection.setRemoteDescription(desc, function () {
      peerConnection.createAnswer(gotLocalDescription, handleError);
    }, handleError);
  } else {
    // 接收到 ICE 候选时,让 RTCPeerConnection 收集它,稍后它将在这些候选方式中挑选最佳者建立连接
    // 注意:RTCPeerConnection 要在 setLocalDescription 后才能开始收集 ICE 候选
    peerConnection.addIceCandidate(new RTCIceCandidate(message.candidate));
  }
});

下期预告

本文简述了点对点连接的建立过程中,双方信息交换的流程。

事实上,在 WebRTC 的技术规范中并没有规定这些信息交换要通过什么途径进行,而是把选择的自由留给留给上层的应用程序。在开发 Web App 时,我们可能最先想到的是 WebSocket,但是也可以采用 SIP 或者 Jingle,或者 XMPP 信息服务比如 OpenFire 之类,等等。在本文中,我们使用了 WebSocket 实现信令交换。

信令服务的任务并不止于连接的建立过程。我们还需要把诸如有人加入聊天、有人挂断这样的信息通知给所有客户端。这些信息既可以用与建立连接时相同的机制进行交换,也可以用 WebRTC RTCDataChannel,这是 WebRTC 的数据传送通道,但这个通道只能在点对点连接建立好以后才能使用,也就是说它不能代替 WebSocket 等,但可以在连接建立后把信令交换的任务接管过来。

WebRTC 之服务器 将会介绍如何使用 node.js 和 socket.io 建立一个 WebSocket 服务器,以提供信令服务;以及如何搭建 STUN/TURN 服务器。


https://hyjk2000.github.io/2015/05/16/webrtc-peer-connection/


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WebRTC 之点对点连接——浏览器 的相关文章

随机推荐

  • gerrit提交出现remote rejected change closed错误

    看了这边文章 原因就像提示信息所说3203已经关闭了 change id找不到了 分析了原因 我的问题是因为之前的一次提交 3203 anandoned掉了 所以找不到这个change id 将这次提交重新恢复后 push成功
  • 区块链技术实战学习路线图

    请大家前往深入浅出区块链主站 获取最新内容 本章的文章越来越多 本文是一个索引帖 方便找到自己感兴趣的文章 你也可以使用左侧的分类 标签及搜索功能 有新文章时会更新本文 建议大家加入收藏夹中 如果你觉得本站不错 欢迎你转发给朋友 引言 给迷
  • 编写简单的linux shell脚本

    1 touch hello sh 2 vi hello sh 键入i 插入 bin sh echo hello world 键入 esc wq 3 chmod 700 hello sh 4 执行 hello sh
  • linux 上生成图片的问题 (awt)

    1 启动xwindow 执行命令 xhost local 2 参考下面资料 原因 Linux无图形支持环境配置 解决 在catalina sh 中加入 Djava awt headless true 或者在 bash profile中增加
  • Redis持久化AOF

    目录 1 AOF简介 2 AOF持久化流程 3 AOF默认不开启 4 AOF和RDB同时开启 redis听谁的 5 AOF启动 修复 恢复 6 AOF同步频率设置 7 Rewrite压缩 7 1 是什么 7 2 重写原理 如何实现重写 8
  • 微信小程序:自动生成打卡海报

    文章目录 1 前言 2 界面展示 3 部分代码展示以及原理解释 4 结语 完整项目下载 下载链接 1 前言 在当前的背单词小程序开发中 为满足用户学习完成后的展示需求 计划引入自动生成打卡海报功能 以提升用户参与度与推广效果 除了基本的海报
  • Window XP驱动开发(十三) 芯片功能驱动端 (代码实现,针对USB2.0 芯片CY7C68013A)

    转载请标明是引用于 http blog csdn net chenyujing1234 欢迎大家提出意见 一起讨论 需要源码的可以与我联系 针对USB2 0 芯片CY7C68013A FPGA实现的高速传输应用来写XP下的USB驱动程序 说
  • 医学图像配准工具Elastix的配置和入门

    一 Elastix介绍 Elastix是一个基于ITK开发的处理医学图像配准问题的工具 Elastix提供了很方便的命令行使用方式以供使用者进行配准应用 同时Elastix是开源的 并且采用模块式构成 可以根据源代码进行开发 或者添加新的模
  • 在LinuxBridge/OVS中使用VxLAN组网以及创建VTEP

    原文来自于 https blog lofyer org E5 9C A8linux bridge ovs E4 B8 AD E4 BD BF E7 94 A8vxlan E7 BB 84 E7 BD 91 E4 BB A5 E5 8F 8A
  • 【满分】【华为OD机试真题2023 JS】箱子之形摆放

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 箱子之形摆放 知识点数组 时间限制 1s 空间限制 128MB 限定语言 不限 题目描述 有一批箱子 形式为字符串 设为str 要求将这批箱子按从上到下以之形的顺序摆放在宽度为n
  • js的事件执行机制(Event loop)

    同步任务 执行主线程上排队执行的任务 只有前一个任务执行完毕 下一个任务才会开始执行 异步任务 不进入主线程 而进入 任务队列 task queue 的任务 只有 任务队列 通知主线程 某个异步任务可以执行了 该任务才会进入主线程执行 事件
  • docker安装nginx太多坑了,果断放弃

    以下是我本人的个人看法 如有不对可在评论区讨论交流 1 listen的端口受限于docker p的参数 一个nginx容器conf文件只能listen同一个端口 2 修改配置文件麻烦 还有docker exec进入到容器内部进行操作 当然
  • 医疗保健软件必备指南

    对许多人来说 软件可能是一种奢侈品 只会给生活在 21 世纪的人们带来一些额外好处 但有时 软件可能是救命稻草 起着生死攸关的作用 根据医疗行业的部分统计数据 我们清醒地发现 美国平均每年约有 25 万至 40 万患者死于本可预防的医疗差错
  • Qt队列的使用

    一 queue 队列 队列是一种先进先出的数据结构 是一个模板类 队列和栈是一种数据逻辑概念 即数据能进行的操作 主要区别是 队列先进先出 First In First Out 栈后进先出 链表和顺序表是一种数据存放方式 主要区别是 链表有
  • 向日葵远程连接Ubuntu出现 “连接中断“ 的解决方法

    向日葵远程连接Ubuntu出现 连接中断 的解决方法 https www cnblogs com wangling1820 p 13448397 html 方法一 参考博客1 https blog csdn net wzf20162016
  • styled-components 的用法

    用于给标签或组件添加样式 给标签或组件添加样式 import styled from styled components styled button 给button标签添加样式 const Button styled button back
  • opencv中归一化函数cv2.normalize()的原理讲解

    本篇文章参考博客 https blog csdn net kuweicai article details 78988886 功能 归一化函数 参数 Python cv2 normalize src dst alpha beta norm
  • 转:在内核里写i2c client 驱动的两种方式

    原文位置 https www cnblogs com simonshi archive 2011 02 24 1963426 html 在内核里写i2c client 驱动的两种方式 前文介 绍了利用 dev i2c 0在应用层完成对i2c
  • 局域网下ROS多机通信的网络连接配置

    1 在路由器设置中固定各机器IP地址 在浏览器中输入路由器的IP地址 例如TP LINK路由器的IP为 192 168 1 1 进入登录页面后 输入用户名和密码登录 用户名一般为admin 密码为自定义 在 基本设置 gt LAN设置 gt
  • WebRTC 之点对点连接——浏览器

    WebRTC 的精髓 点对点连接 上一篇文章中 主要讲了浏览器怎样获取用户设备上的视频流 并且显示在 HTML5