WebRTC:确定所选的 ICE 候选者
WebRTC: Determine the chosen ICE candidate
我有一个 webrtc 应用程序,假设有两个客户端(client1
和 client2
),有什么方法可以找出 client1
给出的 ICE 候选被使用client2
反之亦然?因为,每次找出这个,我都必须在两个客户端上使用 wireshark
,我认为阅读 sdp
可能会有所帮助,但我错了,因为它给出了所有可能的候选人......
场景: client1 的所有 UDP
端口被阻止(为了测试目的而阻止了我)。
Client1 的 SDP:
...
a=rtcp:49407 IN IP4 <client1's IP>
a=candidate:3864409487 1 udp 2122194687 <client1's IP> 49407 typ host generation 0 // this would never work, since the udp ports are blocked...
a=candidate:3864409487 2 udp 2122194687 <client1's IP> 49407 typ host generation 0
a=candidate:2832583039 1 tcp 1518214911 <client1's IP> 0 typ host tcptype active generation 0
a=candidate:2832583039 2 tcp 1518214911 <client1's IP> 0 typ host tcptype active generation 0
a=candidate:973648460 1 udp 25042687 <TURN server IP> 64790 typ relay raddr <Proxy IP> rport 39963 generation 0
a=ice-ufrag:YSvrOiav8TglpCWD
...
嗯,从我的转到另一个问题
我编写并测试了下面的代码,适用于最新版本的 firefox 和 chrome,getConnectionDetails
returns 一个解决连接细节的承诺:
function getConnectionDetails(peerConnection){
var connectionDetails = {}; // the final result object.
if(window.chrome){ // checking if chrome
var reqFields = [ 'googLocalAddress',
'googLocalCandidateType',
'googRemoteAddress',
'googRemoteCandidateType'
];
return new Promise(function(resolve, reject){
peerConnection.getStats(function(stats){
var filtered = stats.result().filter(function(e){return e.id.indexOf('Conn-audio')==0 && e.stat('googActiveConnection')=='true'})[0];
if(!filtered) return reject('Something is wrong...');
reqFields.forEach(function(e){connectionDetails[e.replace('goog', '')] = filtered.stat(e)});
resolve(connectionDetails);
});
});
}else{ // assuming it is firefox
return peerConnection.getStats(null).then(function(stats){
var selectedCandidatePair = stats[Object.keys(stats).filter(function(key){return stats[key].selected})[0]]
, localICE = stats[selectedCandidatePair.localCandidateId]
, remoteICE = stats[selectedCandidatePair.remoteCandidateId];
connectionDetails.LocalAddress = [localICE.ipAddress, localICE.portNumber].join(':');
connectionDetails.RemoteAddress = [remoteICE.ipAddress, remoteICE.portNumber].join(':');
connectionDetails.LocalCandidateType = localICE.candidateType;
connectionDetails.RemoteCandidateType = remoteICE.candidateType;
return connectionDetails;
});
}
}
//usage example:
getConnectionDetails(pc).then(console.log.bind(console));
在chrome中我使用了这个:
let pc1 = new RTCPeerConnection(cfg);
pc1.addEventListener('connectionstatechange', async (e) => {
if (pc1.connectionState === 'connected') {
// Peers connected!
let stats = await pc1.getStats();
for (const value of stats.values()) {
if(value.type=="local-candidate" || value.type=="remote-candidate")
console.log(value);
}
}
})
这个问题很老了,但这是 2021 年可靠的方法! - 至少对我来说。
您可以使用 RTCIceTransport.getSelectedCandidatePair() method which returns an RTCIceCandidatePair 对象(本地和远程 ice-candidate 对)。
示例:
从对等连接中获取用于发送媒体的选定候选对。
peerConnection.getSenders().map(sender => {
const kindOfTrack = sender.track?.kind;
if (sender.transport) {
const iceTransport = sender.transport.iceTransport;
const logSelectedCandidate = (e) => {
const selectedCandidatePair = iceTransport.getSelectedCandidatePair();
console.log(`SELECTED ${kindOfTrack || 'unknown'} SENDER CANDIDATE PAIR`, selectedCandidatePair);
};
iceTransport.onselectedcandidatepairchange = logSelectedCandidate;
logSelectedCandidate();
} else {
// retry at some time later
}
});
以上对于在对等连接对象上接收到的媒体的工作方式类似。
使用 RTCPeerConnection.getReceivers()
代替,在那种情况下
我有一个 webrtc 应用程序,假设有两个客户端(client1
和 client2
),有什么方法可以找出 client1
给出的 ICE 候选被使用client2
反之亦然?因为,每次找出这个,我都必须在两个客户端上使用 wireshark
,我认为阅读 sdp
可能会有所帮助,但我错了,因为它给出了所有可能的候选人......
场景: client1 的所有 UDP
端口被阻止(为了测试目的而阻止了我)。
Client1 的 SDP:
...
a=rtcp:49407 IN IP4 <client1's IP>
a=candidate:3864409487 1 udp 2122194687 <client1's IP> 49407 typ host generation 0 // this would never work, since the udp ports are blocked...
a=candidate:3864409487 2 udp 2122194687 <client1's IP> 49407 typ host generation 0
a=candidate:2832583039 1 tcp 1518214911 <client1's IP> 0 typ host tcptype active generation 0
a=candidate:2832583039 2 tcp 1518214911 <client1's IP> 0 typ host tcptype active generation 0
a=candidate:973648460 1 udp 25042687 <TURN server IP> 64790 typ relay raddr <Proxy IP> rport 39963 generation 0
a=ice-ufrag:YSvrOiav8TglpCWD
...
嗯,从我的
我编写并测试了下面的代码,适用于最新版本的 firefox 和 chrome,getConnectionDetails
returns 一个解决连接细节的承诺:
function getConnectionDetails(peerConnection){
var connectionDetails = {}; // the final result object.
if(window.chrome){ // checking if chrome
var reqFields = [ 'googLocalAddress',
'googLocalCandidateType',
'googRemoteAddress',
'googRemoteCandidateType'
];
return new Promise(function(resolve, reject){
peerConnection.getStats(function(stats){
var filtered = stats.result().filter(function(e){return e.id.indexOf('Conn-audio')==0 && e.stat('googActiveConnection')=='true'})[0];
if(!filtered) return reject('Something is wrong...');
reqFields.forEach(function(e){connectionDetails[e.replace('goog', '')] = filtered.stat(e)});
resolve(connectionDetails);
});
});
}else{ // assuming it is firefox
return peerConnection.getStats(null).then(function(stats){
var selectedCandidatePair = stats[Object.keys(stats).filter(function(key){return stats[key].selected})[0]]
, localICE = stats[selectedCandidatePair.localCandidateId]
, remoteICE = stats[selectedCandidatePair.remoteCandidateId];
connectionDetails.LocalAddress = [localICE.ipAddress, localICE.portNumber].join(':');
connectionDetails.RemoteAddress = [remoteICE.ipAddress, remoteICE.portNumber].join(':');
connectionDetails.LocalCandidateType = localICE.candidateType;
connectionDetails.RemoteCandidateType = remoteICE.candidateType;
return connectionDetails;
});
}
}
//usage example:
getConnectionDetails(pc).then(console.log.bind(console));
在chrome中我使用了这个:
let pc1 = new RTCPeerConnection(cfg);
pc1.addEventListener('connectionstatechange', async (e) => {
if (pc1.connectionState === 'connected') {
// Peers connected!
let stats = await pc1.getStats();
for (const value of stats.values()) {
if(value.type=="local-candidate" || value.type=="remote-candidate")
console.log(value);
}
}
})
这个问题很老了,但这是 2021 年可靠的方法! - 至少对我来说。
您可以使用 RTCIceTransport.getSelectedCandidatePair() method which returns an RTCIceCandidatePair 对象(本地和远程 ice-candidate 对)。
示例: 从对等连接中获取用于发送媒体的选定候选对。
peerConnection.getSenders().map(sender => {
const kindOfTrack = sender.track?.kind;
if (sender.transport) {
const iceTransport = sender.transport.iceTransport;
const logSelectedCandidate = (e) => {
const selectedCandidatePair = iceTransport.getSelectedCandidatePair();
console.log(`SELECTED ${kindOfTrack || 'unknown'} SENDER CANDIDATE PAIR`, selectedCandidatePair);
};
iceTransport.onselectedcandidatepairchange = logSelectedCandidate;
logSelectedCandidate();
} else {
// retry at some time later
}
});
以上对于在对等连接对象上接收到的媒体的工作方式类似。
使用 RTCPeerConnection.getReceivers()
代替,在那种情况下