范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

WebRTC成为HTML5标准?SDPSTUNTURN你想知道的都在这里!

  #头条创作挑战赛#
  大家好,很高兴又见面了,我是" 前端进阶 ",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
  1.前言1.1 什么是 WebRTC?
  下图展示了不同协议出现的时间线:
  在计算机网络中,协议是一组规则,用于管理数据在设备之间的交换方式。 协议定义了通信的规则、语法、语义和同步以及可能的错误恢复方法,本文中讨论的 WebRTC 协议定义了应用层软件如何相互交互。
  WebRTC(Web Real-Time Communication)也被称为网络实时通信,是由 Google、Mozilla 和其他公司推动的一个开源项目,它通过 Javascript API 实现无插件的实时通信,建立浏览器之间点对点(Peer-to-Peer)的连接。 1.2 WebRTC 的优点?
  WebRTC 的优点可以归纳为以下几个方面: 开源、免费,开发者不需要承担高昂的专利费用 基于浏览器,不需要安装插件,只要调用 API 就可以实现音视频互动 被纳入了 HTML5 标准,主流浏览器全面支持 WebRTC 不仅支持 Web 之间的音视频通讯,还支持 Android 以及 IOS 端,由于该项目是开源的,我们也可以通过编译 C++代码,从而达到全平台的互通
  在 WebRTC 诞生之前,开发实时音视频应用的成本是非常高,需要考虑的技术问题很多,如音视频的编解码, 数据传输延时、丢包、网络抖动、回音处理和消除 等,如果要兼容浏览器端的实时音视频通信,还需要额外安装插件。可喜的是,本文的主角 WebRTC 在 2021 年 1 月被 W3C 和 IETF 发布为正式标准,而且得到了大多数主流浏览器的支持。
  WebRTC 项目的愿景:实时通信 web 化,让 WebRTC 成为互联网音视频实时通信的规范,让开发者基于此规范快速开发出安全、可靠的应用。WebRTC 必须在 HTTPS 环境下运行,你可以在https://appr.tc/、https://snapdrop.net/体验WebRTC应用,或者在
  https://nashaofu.github.io/webrtc-demo/,https://webrtc.github.io/samples/查看WebRTC示例。 2.了解SDP和Offer-Answer模型2.1 什么是RTP/RTCP?
  大多数人已经了解 TCP 和 UDP 等传输协议,当您要保证传输数据准确(例如:邮件)时,TCP 协议更好,而 UDP则更加偏向传输速度(例如:YouTube 视频)。
  实时传输协议 (Real-time Transport Protocol,RTP) 又是一种用于通过 IP 网络传送音频和视频的网络协议。 RTP 广泛用于涉及流媒体的通信和娱乐系统,例如电话、视频电话会议、电视服务等。 作为一种电信标准,WebRTC 正在使用 RTP 传输实时数据。
  RTP 控制协议 (RTP Control Protocol ,即RTCP) 是实时传输协议 (RTP) 的兄弟协议。 RTCP 为 RTP 会话提供额外统计和控制信息。 使用 RTCP您可以获得有关数据传输成功的数据,例如"传输过程中发生了多少数据包丢失"、"数据包延迟是多少"或"视频通话的分辨率是多少"等等。
  RTP 和 RTCP 数据包的传输发生在媒体通道上,而WebRTC 负责媒体通道上的媒体传输。作为应用程序开发人员,您的责任是管理信令通道。 所以你通常不知道这些概念,而且大多数时候你不需要它们,但在开始 SDP 和 Offer-Answer 模型之前有必要先了解下 RTP/RTCP 。2.2 什么是SDP(Session Description Protocol)?
  现实生活中,如果您想让人们联系到您,您会分享您的联系信息,比如电子邮件、电话号码、Instagram 帐户、家庭住址等。 分享此类信息的最简单方法是向他们提供您的名片,而为了能够找到对方, 互联网数字名片可能包含以下信息:主叫方和被叫方IP 地址支持哪些媒体类型(音频、视频、屏幕共享等)当前启用或禁用了哪些媒体类型(视频开/关保持/取消保持等)对方都支持哪些编解码器类型
  在电信领域,称这种数字名片为会话描述协议 (SDP), SDP 包含对等点相互交谈所需的信息。WebRTC 也使用 SDP 作为通信标准来发起呼叫, SDP 只是一个可以被端点解析和操作的文本。
  例如,如果用户想要保持通话,您可以通过将 SDP 作为应用程序进行操作来禁用/启用视频和音频流。 或者您的系统需要特定的视频编解码器,比方说 H.264,您可以删除除 H.264 之外的任何其他编解码器。
  这就是 SDP 的强大之处,它很容易根据您的要求进行操作
  下面是一个 SDP 示例,可能包含以下信息:o=alice 2890844526 2890844526 IN IP4 10.48.1.2 //O=表示呼叫的发起者、会话ID和发起者的IP地址 t=0 0 //t= 表示会话结束时间。如果为 0,则表示会话不受时间限制 m=audio 49170 UDP/TLS/RTP/SAVPF 111 0 // m=表示media line,是session中可以存在的媒体属性。 在这种情况下,它表示音频媒体线。 此行还包含将在会话中使用的传输协议 (UDP/TLS/RTP/SAVPF)。 最后,此行包含将在会话中使用的编解码器有效载荷编号 (111, 0) c=IN IP4 217.345.789.123 // c=表示连接信息,比如你要调用的远程设备的IP地址 a=sendrecv a=rtpmap:111 opus/48000/2 a=rtpmap:0 PCMU/8000 //a= 表示属性线。 它定义会话和媒体行属性。 在第一行中,a=sendrcv 属性表示设备愿意发送和接收音频媒体,他还 可以有其他值,如 recvonly、sendonly 或 inactive用于不同的场景,如保持或视频关闭 // Rtpmap 属性指示音频编解码器编号的映射。 在这种情况下,111 映射到具有 48,000 bps 带宽的 Opus,而 0 映射到具有 8,000 bps 带宽的 PCMU 编解码器, 标准 SDP 中可以有更多的属性行。 m=video 51372 UDP/TLS/RTP/SAVPF 98 100 //m= 也表示媒体行,在这种情况下,它表示视频媒体线。同样,它包含传输协议和编解码器有效负载编号。 a=sendrecv a=rtpmap:98 VP9/90000 a=rtpmap:100 H264/90000 //a= 表示属性行。 在第一行中,a=sendrcv 属性表示设备愿意发送和接收视频媒体 //rtpmap 值,98 映射到具有 90,000 bps 带宽的 VP9 视频编解码器,100 映射到具有 90,000 bps 带宽的 H.264 视频编解码器
  SDP的更多属性配置可以阅读文末资料,这里不再展开。2.3 什么是Offer-Answer模型?
  到目前为止,解释了"WebRTC 如何在媒体通道中传输数据?"(RTP/RTCP)和"如何在信令通道中根据需要指定会话属性?"(SDP)。 接下来回答"应用程序应该如何相互传输会话属性 (SDP)?"。
  你可能有一张华丽的名片,但如果你不把它送给任何人,它就毫无用处, 此规则也适用于 SDP。 我们需要在对等点之间交换 SDP 以发起呼叫。 Offer-Answer 模型是在 WebRTC 中用作电信标准的 SDP 交换过程,交换方式由申请时决定。 应用程序可以通过 HTTP/HTTPS 请求、Web 套接字、推送通知等方式发送它。这完全取决于应用程序。
  Offer-Answer模型顾名思义,在这个模型中有一个 Offerer 和一个 Answerer。 提供者是启动信令过程的人,例如开始拨出电话或发送通话事件的人,包括保持和关闭视频开关。 回答者是回答传入提议的人, 例如接听来电或向通话中事件发送合适的数据。
  Offer-Answer 模型有 4 个基本步骤;Offerer 创建一个 Offer SDP 并将其发送到远程节点。应答者收到提议者的 SDP,并自行设置。Answerer 创建一个 Answer SDP 并将其发送给 offerer提供者收到应答者的 SDP,并自行设置。
  之后,如果一切正常,呼叫开始。2.4 WebRTC的Offer-Answer模型交换流程
  下图显示了 WebRTC 上使用 Offer-Answer 模型的 SDP( Session Description Protocol,即会话描述协议) 交换过程:
  接下来一一说明这些步骤: Peer-1 获取用户媒体,然后从 WebRTC 创建一个 PeerConnection 对象 创建PeerConnection后,应用程序需要调用WebRTC的createOffer接口 WebRTC 创建一个Offer SDP ,并且可以根据需要操作 SDP 应用程序应将 Offer SDP 设置回 WebRTC 应用程序应向 Peer-2 发送Offer SDP Peer-2 上的应用程序收到Offer SDP, Peer-2 应该获取用户媒体并创建 PeerConnection 对象(如果目前尚未创建) Peer-2 上的应用程序将Offer SDP 设置给 WebRTC Peer-2 上的应用程序使用 WebRTC 的 createAnswer API 生成应答 SDP WebRTC 创建一个应答 SDP 并将其提供给应用程序,应用程序可以根据需要操作SDP 应用程序应将 Answer SDP 设置给 WebRTC Peer-2 上的应用程序应将应答 SDP 发送给 Peer-1 Peer-1 上的应用程序设置应答 SDP 如果一切正常,RTP 媒体流将通过 WebRTC 在媒体通道上启动。
  上面可能有很多步骤,但其中大部分都是重复性任务。 WebRTC 交换 offer 与网络参数之后,就会尝试直接使用对方的 IP 地址与端口进行直连,这个过程会根据双方网络情况,使用的不同的方式建立连接,后文 NAT(Network Address Translation,即网络地址转换)打洞就是介绍这部分内容。 3.什么是信令服务器?什么是STUN?什么是TURN?
  A 与 B 在建立 WebRTC 连接过程中,需要互相知道对方的 IP 与通信端口。那么 A 与 B 要如何知道对方的 IP 与端口呢?答案就是通过信令服务器。 信令服务器的作用是作为一个中间人帮助双方在尽可能少的暴露隐私的情况下建立连接。WebRTC 并没有提供信令传递机制,你可以使用任何方式如 WebSocket 或者 XMLHttpRequest 等,来交换彼此的令牌信息。
  STUN 和 TURN 服务器是两种类型的 WebRTC 信令服务器,可用于在构建实时通信应用程序时创建对等 (P2P) 连接。 3.1 什么是STUN?
  STUN(NAT 会话遍历实用程序)使用 UDP 协议通过 NAT 来实现 ICE能力。 STUN 允许应用程序发现它们之间和公共互联网上的 NAT 、防火墙的存在和类型。 任何设备都可以使用它来确定 NAT 分配给它的 IP 地址和端口。
  通常,STUN 客户端可以向 STUN 服务器发送消息以获取公共 IP 和端口信息,然后基于此公共 IP 和端口信息即可在客户端之间通过互联网进行点对点通信。3.2 什么是TURN?
  TURN(Traversal Using Relays around NAT)是一种协议,可协助 webRTC 应用程序穿越网络地址转换器 (NAT) 或防火墙。 TURN Server 允许客户端通过中间服务器发送和接收数据, TURN 协议是 STUN 的扩展。
  在少数情况下,客户端通信端点在不同类型的 NAT 后面,或者当使用对称 NAT 时,通过中继服务器及其称为 TURN 服务器发送媒体可能更容易。4.WebRTC API 调用4.1 RTCPeerConnection
  RTCPeerConnection 用于点对点之间建立连接以传输音视频数据流,这是 RTCPeerConnection 的任务,为此需要借助一个信令服务器(signaling server)来进行,信令包括 3 种类型的信息: Session control messages: 初始化和关闭通信,及报告错误; Network configuration: 双方的 IP 地址和端口号(局域网内部 IP 地址需转换为外部的 IP 地址); Media capabilities: 双方的浏览器支持使用何种编码以及多高的视频分辨率。  var PeerConnection =   window.RTCPeerConnection ||   window.mozRTCPeerConnection ||   window.webkitRTCPeerConnection; navigator.getUserMedia = navigator.getUserMedia   ? "getUserMedia"   : navigator.mozGetUserMedia   ? "mozGetUserMedia"   : navigator.webkitGetUserMedia   ? "webkitGetUserMedia"   : "getUserMedia"; var v = document.createElement("video"); // 创建信令(createOffer) var pc = new PeerConnection(); pc.addStream(video); pc.createOffer(function (desc) {   pc.setLocalDescription(desc, function () {     // send the offer to a server that can negotiate with a remote client   }); }); // 创建回复(createAnswer) var pc = new PeerConnection(); pc.setRemoteDescription(new RTCSessionDescription(offer), function () {   pc.createAnswer(function (answer) {     pc.setLocalDescription(answer, function () {       // send the answer to the remote connection     });   }); });4.2 RTCDataChannel
  RTCDataChannel 接口代表在两者之间建立了一个双向数据通道的连接,可以用
  RTCPeerConnection.createDataChannel() 或者在现有的 RTCPeerConnection 上用 RTCDataChannelEvent 类型的 datachannel 事件接收,创建出 RTCDataChannel 类型的对象。 var pc = new RTCPeerConnection(); // 获取 RTCPeerConnection 对象 var dc = pc.createDataChannel("my channel"); // 创建 DataChannel 对象 dc.onmessage = function (event) {   console.log("received: " + event.data); }; dc.onopen = function () {   console.log("datachannel open"); }; dc.onclose = function () {   console.log("datachannel close"); };4.3 访问用户摄像头及麦克风 getUserMedia
  WebRTC 支持直接传输音频流和视频流(https://appr.tc/): const pc = new RTCPeerConnection() ; // 获取RTCPeerConnection navigator.getUserMedia({ video: true }, stream => {    // 添加视频流到会话中   stream.getTracks().forEach(track => pc.addTrack(track, stream))    // 在网页中预览自己摄像头拍摄到的内容,其中$localVideo表示一个Video对象   $localVideo.srcObject = stream;  })
  navigator.getUserMedia()还可以和web Audio API相结合,用来处理音频效果: var range = document.querySelector("input"); window.AudioContext = window.AudioContext || window.webkitAudioContext; var audioCtx = new AudioContext(); navigator.getUserMedia({     audio: true }, function(stream) {     // 创建音频流     var source = audioCtx.createMediaStreamSource(stream);     // 双二阶滤波器     var biquadFilter = audioCtx.createBiquadFilter();     biquadFilter.type = "lowshelf";     biquadFilter.frequenc.value = 1000;     biquadFilter.gain.value = range.value;     source.connect(biquadFilter);     biquadFilter.connect(audioCtx.destination); }, function(error) {     console.log(error); });
  其实,WebRTC并不只是用来做视频、音频,它还可以用来传输任意数据,包括文件,文本等。上面代码示例可以看到,WebRTC规定了 dataChannel 这个双工数据通道,而https://snapdrop.net/这个网站就是通过WebRTC进行文件分享。 const pc = new RTCPeerConnection()  const dataChannel = pc.createDataChannel("chat")  // 监听datachannel事件 pc.addEventListener("datachannel", event => {    // 接收通信方发送过来的数据   event.channel.addEventListener("message", event => {      console.log("message", event.message)    })  })  dataChannel.addEventListener("open", () => {    // 发送数据,可发送任意数据    dataChannel.send("Hi!")  })  dataChannel.addEventListener("close", event => {  }) 4.4 candidate 事件
  当 RTCPeerConnection 实例执行 setLocalDescription()后,RTCPeerConnection 就会探测自己的网络环境,然后用 candidate 事件返回候选网络环境数据,网络环境数据中最重要的是 IP 地址与端口组成的候选通信地址。 candidate 事件中的 event.candidate 主要包含以下几个部分: 本机 IP 地址 本机用于 WebRTC 通信的端口号 候选者类型,包括 host、srflx 和 relay 优先级 传输协议
  具体数据结构的示例如下: {   address: "192.168.31.67",   candidate:     "candidate:2147606101 1 udp 2122260223 192.168.31.67 57959 typ host generation 0 ufrag EaWw network-id 1 network-cost 10",   component: "rtp",   foundation: "2147606101",   port: 57959,   priority: 2122260223,   protocol: "udp",   relatedAddress: null,   relatedPort: null,   sdpMLineIndex: 0,   sdpMid: "0",   tcpType: null,   type: "host",   usernameFragment: "EaWw", };
  candidate 事件 type 字段取值分别为 host、srflx、relay: host(Host candidate) :从本地网卡上获取的地址 srflx(Server reflexive candidate) :STUN(Session Traversal Utilities for NAT,即 NAT 会话穿越应用程序) 返回的该客户端的地址 relay(Relay reflexive candidate): :TURN (Traversal Using Relay NAT,即通过 Relay 方式穿越 NAT)服务器为该客户端分配的中继地址
  本地的 candidate 与远端 candidate 构成的每一对都有一定的优先级,按优先级排序进行连通性检查。最后从有效的 candidate 组合中选择优先级最高的作为传输地址,用于建立 P2P 连接。 5.网络地址转换(NAT)
  网络地址转换(英语:Network Address Translation,缩写:NAT;又称网络掩蔽、IP 掩蔽)在计算机网络中是一种在 IP 数据包通过路由器或防火墙时重写来源 IP 地址或目的 IP 地址的技术。这种技术被普遍使用在有多台主机但只通过一个公有 IP 地址访问互联网的私有网络中。 要建立一个连接需要知道对方的 IP 地址和端口号,在局域网里面一台路由器(基站)可能会连接着很多台设备,例如家庭路由器接入宽带的时候,宽带服务商会分配一个公网的 IP 地址,所有连到这个路由器的设备都共用这个公网 IP 地址。如果两台设备都用了同一个公网 IP:port 去发送请求,服务器返回数据在经过路由器时它就不知道应该转发给哪一个设备。因此路由器需要重写 IP 地址/端口号进行区分,如下图所示:
  NAT 设备通常会自动设置各个设备的映射关系,也可以在路由器端去手动设置。如上图的 NAT 维护的映射关系还会和要访问的目标 IP 地址进行绑定,例如同一终端使用同一端口访问不同的目标 IP,就会建立不同的映射关系。
  如上示例 NAT 上建立的映射关系如下:
  内网 IP 端口
  外网 IP 端口
  NAT 对外 IP 与端口
  192.168.1.2:8080
  39.182.39.30:443
  10.188.20.10:8000
  192.168.1.2:8080
  39.182.39.40:443
  10.188.20.10:8001
  所以实际存储的映射关系会包含上面 3 部分内容,这样做的目的是保证网络安全。想象如下例子,终端 192.168.1.2:8080 通过路由器使用 10.188.20.10:8000 访问服务器 A,建立 NAT 映射如果为 192.168.1.2:8080-->10.188.20.10:8000,那么如果有人向 10.188.20.10:8000 发送数据就会转发到 192.168.1.2:8080,这样就会导致内网的服务被外部随意访问,所以 NAT 映射会记录目标地址。当然,由于 NAT 有多种类型,NAT 映射也会存不同,更多内容可参考维基百科或者 WebRTC 网络基础 九、第二节 NAT 打洞原理,下表进行一个简单的归纳。
  5.1 NAT 打洞
  由于 NAT 有上面 4 种类型,所以两个设备要建立 P2P 连接就要使用不同的方式。 5.1.1 完全锥型 NAT
  完全锥型是非常简单的 ,左边是内网的主机,它有自己的内网 IP 地址和端口 ,通过防火墙之后,它形成一个外网的 IP 地址,那么外网的主机要想与内网的主机进行通信的时候,首先要由内网的主机向外发送一个请求,请求外网中的其中一台主机,这样会形成的结果就是它会在 NAT 服务上打一个洞,这样会形成一个外网的 IP 地址和端口。 形成了外网的 IP 地址和端口之后, 其他的主机只要获得了这个 IP 地址和端口它都可以向它发送数据 。并且可以顺利的通过防火墙发送给内网的主机。这样就可以进行通讯了,这是完全锥型,也是最好穿越的一种 NAT 类型。但是安全性就差很多。
  NAT内网计算机IP地址为10.0.0.1,其在端口 8000 上收发消息,映射到 NAT 上的外部IP和端口为 202.123.211.25:8000。 这样Internet 上的任何人都可以向 NAT 上的内网 IP: 端口发送数据包,这些数据包将被传递到 10.0.0.1:8000 的客户端机器。5.1.2 地址限制锥型 NAT
  它的安全性好一些,它会在防火墙上形成一个 五元组 ,即内网主机的 IP 地址和端口、映射后的公网 IP 地址和端口、请求的主机 IP 地址。他们首先有一个公共的步骤,第一步就是要先由内网的主机向外网发送一个请求,在这个防火墙上或者 NAT 服务上形成一个映射表,那形成之后外网的主机就可以和内网的主机进行通讯了。
  客户端向服务器 1(IP - 192.248.22.100)发送数据包,然后NAT将客户端的10.0.0.1:8000映射到外网的202.123.211.25:8000, 现在 server1 可以将数据包发送到目的地。 但是,NAT 将阻止来自服务器 2(IP - 192.248.22.200)的数据包,直到客户端向服务器 2 的 IP 地址发送数据包。 一旦客户端将数据包发送到服务器 2,服务器 1 和服务器 2 都可以将数据包发送回客户端。5.1.3 端口限制锥型 NAT
  端口限制型就更加严格一些了,不光是对 IP 地址,还要对端口做限制,所以在防火墙上就形成了 六元组 ,不光有内网的 IP 地址和端口、映射后的公网的 IP 地址和端口、还有你请求的主机的 IP 地址和端口。
  如果客户端将数据包发送到 192.248.22.100:10100(包含IP 和端口),NAT 将只允许来自 192.248.22.131:10100 的数据包(到客户端),它 丢弃 来自 192.248.22.131:10200(相同 ip 但不同端口)的数据包。 5.1.4 对称型 NAT
  对称限制型就更加严格了,以前的类型是在防火墙上形成映射后的公网的 IP 地址是保持不变的,大家要找还是能找到它的,虽然不通,但是对于 这个对称型它就不一样了,它就发生了变化,不光是形成了一个 IP 地址和端口,而且还会形成多个, 对于每一台主机都会形成一个不同的 IP 地址和端口对 。
  如果客户端从 10.0.0.1:8000 发送数据到 server1,其外网地址被映射为 202.123.211.25:12345,而如果客户端从同一个端口(10.0.0.1:8000)发送到不同的 IP,则映射的外网地址也会不同(即外网地址被映射为 202.123.211.25:45678)。  server1 只能响应自己的映射,server2也 只能响应自己的映射,两者无法公用 。 如果任何一个地址尝试发送到另一个映射的 IP:port,这些数据包将被丢弃。 5.2 WebRTC 打洞这么复杂么?
  WebRTC 本身就已经实现 NAT 打洞功能,只需要连接的双方交换了网络端口和 IP 之后,WebRTC 就会自动进行打洞。WebRTC 使用一个叫做交互式连接设施( ICE,Interactive Connectivity Establishment,即交互式连接建立 )协议框架,ICE 整合了 STUN 与 TURN。STUN 是用来探测终端 NAT 类型、IP 和端口的服务,WebRTC 获取到 NAT 类型、IP 和端口后就会触发 candidate 事件,然后连接双方交换 IP 与端口,开始打洞。如果打洞失败,那么就会使用 TURN 服务器转发流量。
  由于 WebRTC 提供了 ICE,所以使用非常简单,只需在 new RTCPeerConnection 时传入 iceServers 参数即可。googel 提供了免费的 STUN 服务器去帮助打洞,也可以自己架设服务器。 const pc = new RTCPeerConnection({   // 可以传入多个 stun 服务器或者 turn 服务器   iceServers: [     { url: "stun:stun.l.google.com:19302" },     { url: "stun:stun1.l.google.com:19302" },     { url: "stun:stun2.l.google.com:19302" },     { url: "stun:stun3.l.google.com:19302" },     { url: "stun:stun4.l.google.com:19302" },   ], });6.WebRTC vs WebSocket 区别用途区别 WebSocket允许浏览器和Web服务器之间进行全双工通信. WebRTC允许两个浏览器之间的全双工通信。
  2. 协议区别 WebSocket使用TCP协议 WebRTC使用UDP协议
  3. 流量路径 WebSocket浏览需要经过服务器 WebRTC是直接连接,浏览不会经过第三方服务器,是一个去中心化的架构模型,简单说就是省带宽。
  4. 实时性 WebSocket延迟高(不是直接连接) WebRTC延迟低
  通常WebRTC会与WebSocket配合使用,WebSocket的作用主要是用来交换客户端的SDP与网络信息,Websocket传输的内容与真正通信数据无关,只是协助WebRTC建立连接。  参考资料
  https://medium.com/orion-innovation-turkey/webrtc-in-a-nutshell-ep-ii-ca8cb33f8ff3
  https://datatracker.ietf.org/doc/html/rfc4566
  https://medium.com/rahasak/network-address-translation-nat-df84dc1cb06c
  https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel
  https://caniuse.com/?search=WebRTC
  https://www.jianshu.com/p/1022f559a805
  https://zhuanlan.zhihu.com/p/421503695
  https://github.com/nashaofu/webrtc-demo
  https://blog.csdn.net/xyphf/article/details/107297616
  https://medium.com/av-transcode/what-is-webrtc-and-how-to-setup-stun-turn-server-for-webrtc-communication-63314728b9d0
  https://webrtc.ventures/2020/12/webrtc-signaling-stun-vs-turn/
  #头条创作挑战赛#

我,在老挝娶小11岁美女,为了给她安全感,花30万在她老家建别墅这是我们讲述的第1559位真人故事我叫梁旭老挝媳妇与禾草大叔,今年37岁。在我17岁之前,曾是让学校家长头痛的不良少年,转过七个中学都没读完高中。走上社会后,我进过工厂,做过销售,浙江卡巴尔电气公司小遥控拨千吨研发最强大脑来源经济日报在卡巴尔电气公司PCBA(全自动电子线路板贴片和自检测)生产车间,工人正对电子线路板进行检查。陈冰曲摄(中经视觉)挖掘隧道的盾构机开凿巷道的掘进机破碎矿料的移动式破碎机中央气象台西北地区东部西南地区东部等地多阴雨雪天气,东南部海域有大风一天气实况1。国内实况昨日川陕渝贵等地出现降雨昨08时至今06时,四川东部陕西南部重庆贵州中北部湖北西南部等地部分地区出现小到中雨新疆南疆西部甘肃东部陕西北部吉林东部等地部分地区出41岁的宠物侦探已帮一千只宠物回家,曾帮韩寒找狗,每天接到全国各地的求助电话41岁的孙锦荣似乎更能理解好奇害死猫的含义。作为一名宠物侦探,在几乎无休的10年职业生涯中,他和团队成员要随时待命,用他的话说,毕竟宠物不会和人约好时间走失。白天找狗,晚上找猫。孙浅谈恩格鲁玛对非洲政治发展的贡献,及非洲人的个性的特点编辑天文叙史文字天文叙史前言克瓦米恩克鲁玛对非洲人格的概念化与他的文化思想有着复杂的联系。他的概念,在许多方面与其他非洲人格的支持者不同。康邦将其定义为非洲人的基本心理和行为特征的家长要适当袒护自己的孩子保护孩子,那肯定是一定的我一开始,太讲究公平公正了。后来有一次,孩子聊天中说了一句我发现,每逢有大事发生,我爸一定站在我这边。当时我就注意到了这句话。一下子让我想起小时候的一件事情我和邻居家小孩玩的时候,漫画那一刻,我觉得自己像个生育工具有数据显示我国产后抑郁的发生率在2268。1。意味着100个怀孕女性里大部分都有人患产后抑郁的概率。最可悲的是身边人的不体谅不理解,而这些女性没有发觉到自己居然生病了。他们就这样一网红款不一定真好用,买儿童牙刷这三点很重要要帮孩子把牙齿刷干净,最重要的是掌握正确的刷牙方法,然后还需要一把好用的牙刷。市面上有着各式各样的儿童牙刷,但有时候刷不干净牙,真不是家长不努力,而是牙刷没选好!现在的儿童牙刷,排孩子肚子家长大小心!出生6天女娃胀得像皮球,竟是出生没有肛门!开了五个小时车,小宝(化名)的父亲抱着孩子从湘西赶到长沙,终于走进了湖南妇女儿童医院。01hr意外刚出生女婴竟无肛门一个月前,韩先生(化名)一家迎来了新生命的诞生,正当全家沉浸在喜试管人必看试管进周后用药的详细分类看完这一篇,你会了解1什么是诱发排卵?2什么是控制性卵巢刺激?3降调促排中的用药有哪些?4诱导排卵(夜针)药物有哪些?5黄体支持药物有哪些?6促排药物怎么选?正常情况下,每位女性每春节四川游客量全国第一,3月10日成都房车展,再掀房车旅游热潮2022年春节假期四川旅游接待人数居全国第一位,房车旅行市场也将迎来更大的发展机遇。成都已然成为房车露营旅游行业最关注之地,房车猫2023第五届成都房车露营博览会由此而生,将于20
杜海涛瘦下来后真变丑了!脸小一圈加秃顶变憔悴不少,还是胖些帅杜海涛近照曝光,可是惊讶到了不少网友,身穿赛车服的他虽然只露出了身影,但是明显瘦了不少的样子,让他也有了帅气的感觉,和沈梦辰站在一起,更是分的般配。不过随后杜海涛的正面照曝光,可是死撑着打的二乌究竟在打什么俄乌对打将进入十六周,本周在战场外,发生了两起让人浮想之事,一是北约秘书长在与芬兰首领会谈后谈到了芬兰曾经的割地求和,这事指的是二战末芬兰划出部分土地给当时的苏联,换得了至今几十年055领头,解放军舰队再进日本海美媒003航母满旗,出坞在即根据日本防卫省统合幕僚监部在6月14日发布的消息显示,解放军舰队在6月13日再次穿越对马海峡,开始进入日本海展开战斗巡航行动,日本海上自卫队派出了海空力量,对于解放军舰队进行了严密恭喜!中国体坛又一对神仙眷侣队友变爱人,相恋十一年官宣结婚年初的冬奥会,让很多国人第一次见识到了冰雪运动的魅力,尤其是中国男子冰壶队帅哥云集,颜值高,身材好,荷尔蒙爆棚,吸引了不少女粉丝!有人喜欢姜东旭,有人喜欢王智宇,但是吸粉最多的,还iPhone全球售价对比!日本iPhone最便宜,巴西最贵售价约1。03万元中国经济周刊经济网讯据媒体报道,日本MM综研(位于东京都港区)的调查结果了解到,在对苹果智能手机iPhone在全球34个国家和地区的销售价格进行对比后发现,日本最为便宜。3款最新机真理在射程之内,055万吨大驱再进日本海,日本海空力量紧急出动根据日本防卫省统合幕僚监部发布的公告显示,解放军从6月12日到6月13日,接连出动军舰开始了在日本海的战斗巡航行动。解放军首先出动了一艘综合情报搜集舰进入日本海,在6月13日出动了卫生间一定不要摆放的8样东西,不是迷信,是实用建议这里讲的不要摆放,不是摒弃,而是一种收纳方式的变化,拒绝全部摆在平面上,合理利用空间和工具,该收的收,该挂的挂。然后,你就会发现,卫生间不仅比之前整齐了,还更能长久保持干净,本期分普通人面对暴力事件,应该怎么办?这两天一直在持续关注唐山打人事件,不经想到普通如我们,如果是我们在面对暴力事件的时候,应该怎么办。很多人应该都看到了网络上,一些现场目击者们之后的发声。不是没有人尝试去阻止殴打的行唐山大地震过去46年,而今唐山烧烤店打人案件,再次让国人震惊1976年7月28日3时42分53。8秒,中国河北省唐山丰南一带(东经118。2,北纬39。6)发生了强度里氏7。8级(矩震级7。5级)地震,震中烈度11度,震源深度12千米,地震湖南又1名酒陨落,曾3胜茅台入选中国名酒,如今偏居一隅无人问津现今白酒界,当真竞争激烈,提到白酒,大家第一个想到的便是川贵二地。贵州茅台以一己之力,拉动了全省GDP,根据相关数据可知,茅台股价总市值稳定在1。78万亿元,而贵州省在2019年全唐山打人事件辟谣兼扫盲贴辟谣1。绿衣男只要不是傻子,就不会对着老板娘和两个陌生人说把白衣女怼到路边办了这种话,相比之下,绿衣男是去催菜比较合理。2。四个女孩两个进了医院,现在转入了普通病房,剩下两个伤势较