本文共 6476 字,大约阅读时间需要 21 分钟。
webrtc和rtp的关系
WebRTC和RTP协议的关系
WebRTC和RTP协议的关系
我们知道WebRTC是实现实时通信的核心技术,而RTP协议是实现音视频传输的基础协议。两者之间存在着密切的关联关系。RTP协议全称是实时传输协议(Real-time Transport Protocol),主要用于在网络中传输音频和视频数据。它提供了相对高效的数据传输机制。
在WebRTC中,RTP被用作主要的音视频数据传输协议。这意味着当我们在进行视频会议或者实时通话时,音视频流的传输都基于RTP协议。然而,RTP本身并不具备端到端的可靠性和有序性保证。因此,WebRTC引入了SCTP协议来解决这一问题。
SCTP的作用
SCTP协议全称是流控传输协议(Stream Control Transmission Protocol),它是RTP的补充协议。SCTP不仅支持RTP的传输,还能提供可靠性和有序性。这种机制使得音视频数据在传输过程中能够更加可靠地到达对方端点。
在Chrome浏览器中,可以通过chrome://webrtc-internals/来查看更多关于WebRTC的内部信息。在这个界面中,我们可以看到channel-data-1,这是数据通道的标识符。可以看到Google的 peer 2 peer 系统正使用libjingle来管理时间戳。
技术迭代的原因
为什么WebRTC技术发展如此迅速?这是因为它建立在强大的基础之上。"三个字要分量重"这句话不仅适用于个人修养,也适用于技术开发。作为程序员,我们必须深入理解基础协议的工作原理,才能在技术发展中不断进步。
在开发WebRTC应用时,我们需要深入理解RTP和SCTP的区别和联系。只有这样,才能更好地构建高效的通信系统。在实践中,Zoom公司就是一个很好的案例。他们通过优化DataChannel来实现RTP数据的传输,显著提升了会议的体验和效率。
Web示例代码解析
以下是一个实现WebRTC数据通道的示例代码:
'use strict';var localConnection;var remoteConnection;var sendChannel;var receiveChannel;var pcConstraint;var dataConstraint;dataChannelSend = document.querySelector('textarea#dataChannelSend');dataChannelReceive = document.querySelector('textarea#dataChannelReceive');startButton = document.querySelector('button#startButton');sendButton = document.querySelector('button#sendButton');closeButton = document.querySelector('button#closeButton');startButton.onclick = createConnection;sendButton.onclick = sendData;closeButton.onclick = closeDataChannels;function enableStartButton() { startButton.disabled = false;}function disableSendButton() { sendButton.disabled = true;}function createConnection() { dataChannelSend.placeholder = ''; servers = null; pcConstraint = null; dataConstraint = null; trace('Using SCTP based data channels'); window.localConnection = localConnection = new RTCPeerConnection(servers, pcConstraint); trace('Created local peer connection object localConnection'); sendChannel = localConnection.createDataChannel('sendDataChannel', dataConstraint); trace('Created send data channel'); localConnection.onicecandidate = iceCallback1; sendChannel.onopen = onSendChannelStateChange; sendChannel.onclose = onSendChannelStateChange; window.remoteConnection = remoteConnection = new RTCPeerConnection(servers, pcConstraint); trace('Created remote peer connection object remoteConnection'); remoteConnection.onicecandidate = iceCallback2; remoteConnection.ondatachannel = receiveChannelCallback; localConnection.createOffer().then( gotDescription1, onCreateSessionDescriptionError ); startButton.disabled = true; closeButton.disabled = false;}function onCreateSessionDescriptionError(error) { trace('Failed to create session description: ' + error.toString());}function sendData() { var data = dataChannelSend.value; sendChannel.send(data); trace('Sent Data: ' + data);}function closeDataChannels() { trace('Closing data channels'); sendChannel.close(); trace('Closed data channel with label: ' + sendChannel.label); receiveChannel.close(); trace('Closed data channel with label: ' + receiveChannel.label); localConnection.close(); remoteConnection.close(); localConnection = null; remoteConnection = null; trace('Closed peer connections'); startButton.disabled = false; sendButton.disabled = true; closeButton.disabled = true; dataChannelSend.value = ''; dataChannelReceive.value = ''; dataChannelSend.disabled = true; disableSendButton(); enableStartButton();}function gotDescription1(desc) { localConnection.setLocalDescription(desc); trace('Offer from localConnection \n' + desc.sdp); remoteConnection.setRemoteDescription(desc); remoteConnection.createAnswer().then( gotDescription2, onCreateSessionDescriptionError );}function gotDescription2(desc) { remoteConnection.setLocalDescription(desc); trace('Answer from remoteConnection \n' + desc.sdp); localConnection.setRemoteDescription(desc);}function iceCallback1(event) { trace('local ice callback'); if (event.candidate) { remoteConnection.addIceCandidate( event.candidate ).then( onAddIceCandidateSuccess, onAddIceCandidateError ); trace('Local ICE candidate: \n' + event.candidate.candidate); }}function iceCallback2(event) { trace('remote ice callback'); if (event.candidate) { localConnection.addIceCandidate( event.candidate ).then( onAddIceCandidateSuccess, onAddIceCandidateError ); trace('Remote ICE candidate: \n ' + event.candidate.candidate); }}function onAddIceCandidateSuccess() { trace('AddIceCandidate success.');}function onAddIceCandidateError(error) { trace('Failed to add Ice Candidate: ' + error.toString());}function receiveChannelCallback(event) { trace('Receive Channel Callback'); receiveChannel = event.channel; receiveChannel.onmessage = onReceiveMessageCallback; receiveChannel.onopen = onReceiveChannelStateChange; receiveChannel.onclose = onReceiveChannelStateChange;}function onReceiveMessageCallback(event) { trace('Received Message'); dataChannelReceive.value = event.data;}function onSendChannelStateChange() { var readyState = sendChannel.readyState; trace('Send channel state is: ' + readyState); if (readyState === 'open') { dataChannelSend.disabled = false; dataChannelSend.focus(); sendButton.disabled = false; closeButton.disabled = false; } else { dataChannelSend.disabled = true; sendButton.disabled = true; closeButton.disabled = true; }}function onReceiveChannelStateChange() { var readyState = receiveChannel.readyState; trace('Receive channel state is: ' + readyState);}function trace(text) { if (text[text.length - 1] === '\n') { text = text.substring(0, text.length - 1); } if (window.performance) { var now = (window.performance.now() / 1000).toFixed(3); console.log(now + ': ' + text); } else { console.log(text); }} 这个代码实现了一个基于WebRTC的实时通信系统。它使用SCTP协议来实现数据通道的可靠传输。在代码中,我们可以看到如何创建本地和远程的RTCPeerConnection,并如何通过DataChannel实现实时数据传输。
通过这个示例,我们可以看到WebRTC在实际应用中的架构设计。它结合了RTP协议的高效传输能力和SCTP协议的可靠性保证,形成了一套完整的实时通信解决方案。
在接下来的第三课中,我们将对这个代码进行优化和扩展,使其更具实用性和产品化价值。我们将深入探讨RTP协议和信令服务的实现细节,提升整个系统的性能和可靠性。
转载地址:http://ylbc.baihongyu.com/