156 lines
4.5 KiB
JavaScript
156 lines
4.5 KiB
JavaScript
let A_RTC = new WebSocket("ws://127.0.0.1:8080/RTC");
|
|
|
|
A_RTC.onopen = function(event) {
|
|
console.log("RTC: Connected");
|
|
createOffer().then(r => {
|
|
|
|
});
|
|
}
|
|
|
|
A_RTC.onmessage = function(event) {
|
|
console.log("RTC: Received: " + event.data);
|
|
try {
|
|
const data = JSON.parse(event.data);
|
|
if(data.type === "answer"){
|
|
handleAnswer(data).then(r => {
|
|
|
|
});
|
|
}
|
|
else if(data.type === "candidate"){
|
|
handleCandidate(data)
|
|
}
|
|
}
|
|
catch (e){
|
|
console.log(e);
|
|
}
|
|
}
|
|
|
|
A_RTC.onclose = function(event) {
|
|
console.log("RTC: Close");
|
|
}
|
|
|
|
// 创建PeerConnection
|
|
let peerConnection;
|
|
let dataChannel;
|
|
|
|
function createPeerConnection() {
|
|
peerConnection = new RTCPeerConnection({
|
|
iceServers: [
|
|
// {
|
|
// urls: ['stun:stun.l.google.com:19302']
|
|
// }
|
|
]
|
|
});
|
|
|
|
// 监听 ICE 状态变化
|
|
peerConnection.oniceconnectionstatechange = () => {
|
|
console.log('ICE connection state:', peerConnection.iceConnectionState);
|
|
if (peerConnection.iceConnectionState === 'connected') {
|
|
console.log('ICE 连接成功!');
|
|
// 在 ICE 连接成功后再创建数据通道
|
|
dataChannel = peerConnection.createDataChannel('DataChannel');
|
|
setupDataChannel();
|
|
}
|
|
else if (peerConnection.iceConnectionState === 'failed') {
|
|
console.error('ICE 连接失败,尝试重新协商...');
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
function setupDataChannel() {
|
|
console.log('Setting up DataChannel...');
|
|
dataChannel.onopen = () => {
|
|
console.log('Data channel is open and ready to be used.');
|
|
// 发送初始数据
|
|
sendData('Hello from DataChannel!');
|
|
sendData(JSON.stringify({ command: 'start', time: Date.now() }));
|
|
};
|
|
|
|
dataChannel.onmessage = event => {
|
|
console.log('Received message:', event.data);
|
|
};
|
|
|
|
dataChannel.onclose = () => {
|
|
console.log('Data channel closed.');
|
|
};
|
|
}
|
|
|
|
// 创建Offer
|
|
async function createOffer() {
|
|
createPeerConnection();
|
|
const offer = await peerConnection.createOffer({
|
|
offerToReceiveAudio: true,
|
|
offerToReceiveVideo: false, // 如果不需要视频,可以设置为 false
|
|
});
|
|
await peerConnection.setLocalDescription(offer);
|
|
console.log('Local Description:', peerConnection.localDescription);
|
|
A_RTC.send(JSON.stringify({ type: 'offer', offer: peerConnection.localDescription }));
|
|
}
|
|
|
|
// 处理Answer
|
|
async function handleAnswer(answer) {
|
|
try {
|
|
// 确保传递完整的 RTCSessionDescription 对象
|
|
const remoteDesc = new RTCSessionDescription({
|
|
type: "answer",
|
|
sdp: answer.sdp
|
|
});
|
|
await peerConnection.setRemoteDescription(remoteDesc);
|
|
console.log('Remote Description set successfully.');
|
|
peerConnection.onicecandidate = e => {
|
|
if (e.candidate) {
|
|
A_RTC.send(JSON.stringify({
|
|
type: 'candidate',
|
|
candidate: e.candidate
|
|
}));
|
|
console.log('Candidate sent:', e.candidate);
|
|
}
|
|
};
|
|
|
|
} catch (e) {
|
|
console.error('Failed to set remote description:', e);
|
|
}
|
|
}
|
|
|
|
// 处理Offer
|
|
async function handleOffer(offer) {
|
|
createPeerConnection();
|
|
await peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
|
|
const answer = await peerConnection.createAnswer();
|
|
await peerConnection.setLocalDescription(answer);
|
|
console.log('Local Description:', peerConnection.localDescription);
|
|
A_RTC.send(JSON.stringify({ type: 'answer', answer: peerConnection.localDescription }));
|
|
}
|
|
|
|
// 处理ICE候选
|
|
function handleCandidate(candidate) {
|
|
if (peerConnection) {
|
|
const iceCandidate = new RTCIceCandidate({
|
|
candidate: candidate.candidate,
|
|
sdpMid: candidate.sdpMid,
|
|
sdpMLineIndex: candidate.sdpMLineIndex,
|
|
usernameFragment: candidate.usernameFragment
|
|
});
|
|
peerConnection.addIceCandidate(iceCandidate).then(r => {
|
|
console.log('Candidate added successfully.');
|
|
});
|
|
}
|
|
}
|
|
|
|
// 处理来自DataChannel的数据
|
|
function handleData(data) {
|
|
if (dataChannel) {
|
|
console.log('Received data:', data)
|
|
}
|
|
}
|
|
|
|
// 发送数据到DataChannel
|
|
function sendData(data) {
|
|
if (dataChannel && dataChannel.readyState === 'open') {
|
|
dataChannel.send(data);
|
|
} else {
|
|
console.error('Data channel is not open.');
|
|
}
|
|
}
|