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后,开始搜集 candidate
  peerConnection.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.创建answer
                    createAnswer()
                })
                .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;
}

猜你喜欢

转载自blog.csdn.net/abu935009066/article/details/129540153