- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 React 构建一个 Web 应用程序,用户可以在其中输入群组通话。我有一个运行 Socket.IO 来管理客户端事件的 NodeJS 服务器,用户通过使用简单对等点 (WebRTC) 的点对点连接进行连接。
一切都很实用,从加入通话、看到其他用户到能够离开。调用是“常开”的,类似于discord,用户可以随意来来去去。但是,如果您离开然后在不刷新页面的情况下尝试重新加入通话,则通话会四面八方中断。用户离开并重新加入时出现以下错误:
Error: cannot signal after peer is destroyed
对于通话中的另一用户,它会为尝试重新加入的用户多次记录“用户加入”事件。之前它还会添加多个对等点,但我现在确保不存在重复项。
然而,对我来说,最奇怪的部分是当用户离开时,他们会向房间内的所有其他用户发出调用。其他用户成功地破坏了对等连接,然后从他们的对等阵列中删除该用户。轮到他离开的用户也会破坏每个连接并将对等数组重置为空数组。所以我对它试图重新建立的 PTP 连接感到非常困惑。
const [roomSize, setRoomSize] = useState(0);
const socketRef = useRef();
const userVideo = useRef();
const peersRef = useRef([]);
const roomId = 'meeting_' + props.zoneId;
useEffect(async () => {
socketRef.current = io.connect(SERVER_URI, {
jsonp: false,
forceNew: true,
extraHeaders: {
"x-access-token": window.localStorage.getItem('accessToken'),
"zone-id": props.zoneId
}
});
}, []);
useEffect(async () => {
if (props.active) {
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
height: window.innerHeight / 2,
width: window.innerWidth / 2
},
audio: true });
userVideo.current.srcObject = stream;
console.log(`%cJoined socket at ${SERVER_URI}, connected=${socketRef.current.connected}`, 'color: pink');
socketRef.current.emit("join room", roomId);
socketRef.current.on("all users", users => {
users.forEach(userID => {
const peer = createPeer(userID, socketRef.current.id, stream);
const peerObj = {
peerID: userID,
peer,
};
if (!peersRef.current.find(p => p.peerID === userID))
peersRef.current.push(peerObj);
});
setRoomSize(peersRef.current.length);
console.log(`%cNew Room Members: ${peersRef.current.length}; %o`, 'color: cyan', {peersRef: peersRef.current});
})
socketRef.current.on("user joined", payload => {
const peer = addPeer(payload.signal, payload.callerID, stream);
const peerObj = {
peerID: payload.callerID,
peer,
};
if (!peersRef.current.find(p => p.peerID === payload.callerID))
peersRef.current.push(peerObj);
setRoomSize(peersRef.current.length);
console.log(`%cSomeone Joined. Members: ${peersRef.current.length}; %o`, 'color: cyan', {peersRef: peersRef.current});
});
socketRef.current.on("receiving returned signal", payload => {
/** @type {Peer} */
const item = peersRef.current.find(p => p.peerID === payload.id);
item.peer.signal(payload.signal);
console.log("%creceiving return signal", 'color: lightgreen');
});
socketRef.current.on('user left', id => {
const peerObj = peersRef.current.find(p => p.peerID === id);
// console.log("user left", { peerObj });
if (peerObj)
peerObj.peer.destroy();
const peers = peersRef.current.filter(p => p.peerID !== id);
peersRef.current = peers;
setRoomSize(peersRef.current.length);
console.log(`%cSomeone Left. Members: ${peersRef.current.length}`, 'color: cyan');
});
} catch (err) {
console.trace(err);
}
}
else if (socketRef.current && socketRef.current.connected) {
socketRef.current.emit("leave room");
peersRef.current.forEach(peerObj => {
peerObj.peer.destroy();
});
peersRef.current = [];
setRoomSize(peersRef.current.length);
}
}, [props.active, peersRef.current]);
const createPeer = (userToSignal, callerID, stream) => {
const peer = new Peer({
initiator: true,
trickle: false,
stream,
});
peer.on("signal", signal => {
socketRef.current.emit("sending signal", { userToSignal, callerID, signal })
})
return peer;
}
const addPeer = (incomingSignal, callerID, stream) => {
const peer = new Peer({
initiator: false,
trickle: false,
stream,
})
peer.on("signal", signal => {
socketRef.current.emit("returning signal", { signal, callerID })
})
peer.signal(incomingSignal);
return peer;
}
快速编辑:以上代码是 React 组件的一部分,该组件为每个对等点呈现一个视频元素。
当 props.active
变为 false
时,即用户离开通话。这发生在第二个 useEffect
Hook 的末尾,离开的客户端应该在销毁它们之后删除所有对等对象。为什么此用户在重新连接时收到上述错误?以及如何防止此错误发生?
编辑:我刚刚注意到,当两个用户都离开通话,并且都尝试在不刷新的情况下重新加入时,不会发生错误。因此,我最好的猜测是,在用户离开时删除对等点与离开你自己是不同的。
最佳答案
TLDR;将您在 useEffect
正文中使用的所有 refs 放入 useEffect
deps 数组中。
我一定要先检查 useEffect
deps 数组。看起来整个钩子(Hook)主体的多个位置都需要 socketRef
,但它似乎不在 deps 数组中。这可能会导致 Hook 使用低于当前的数据。
也正因为如此,socketRef
ref 对象可能永远不会实际上更新,这意味着,它可能正确地从对等点中删除用户,因为 peerRefs
在 useEffect
deps 数组中,但是内部 session (房间)可能无法识别它;房间对用户的内部表示仍然存在。
重复一遍,但为了清楚起见,您提到了:
So something is different when removing a peer upon a user leaving compared to leaving yourself is my best guess.
这与上面列出的原因相同。它在对等方离开时发生的原因是因为 peerRefs
ref 对象在 useEffect
deps 数组中,所以您描述的效果只是“完美时机”,如果你会的,因为应用程序状态(所有引用)彼此正确同步。
关于javascript - 为什么WebRTC断开后无法重连?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72245114/
我正在尝试使用谷歌浏览器的 Trace Event Profiling Tool分析我正在运行的 Node.js 应用程序。选择点样本后,我可以在三种 View 之间进行选择: 自上而下(树) 自上而
对于一个可能是菜鸟的问题,我们深表歉意,但尽管在 SO 上研究了大量教程和其他问题,但仍找不到答案。 我想做的很简单:显示一个包含大量数据库存储字符串的 Android ListView。我所说的“很
我已经开始了一个新元素的工作,并决定给 Foundation 5 一个 bash,看看它是什么样的。在创建带有水平字段的表单时,我在文档中注意到的第一件事是它们使用大量 div 来设置样式。所以我在下
我有一个 Windows 窗体用户控件,其中包含一个使用 BeginInvoke 委托(delegate)调用从单独线程更新的第 3 方图像显示控件。 在繁重的 CPU 负载下,UI 会锁定。当我附加
我有一堆严重依赖dom元素的JS代码。我目前使用的测试解决方案依赖于 Selenium ,但 AFAIK 无法正确评估 js 错误(addScript 错误不会导致您的测试失败,而 getEval 会
我正在制作一款基于滚动 2D map /图 block 的游戏。每个图 block (存储为图 block [21][11] - 每个 map 总共 231 个图 block )最多可以包含 21 个
考虑到以下情况,我是前端初学者: 某个 HTML 页面应该包含一个沉重的图像(例如 - 动画 gif),但我不想强制客户缓慢地等待它完全下载才能享受一个漂亮的页面,而是我更愿意给他看一个轻量级图像(例
我正在设计一个小软件,其中包括: 在互联网上获取资源, 一些用户交互(资源的快速编辑), 一些处理。 我想使用许多资源(它们都列在列表中)来这样做。每个都独立于其他。由于编辑部分很累,我想让用户(可能
我想比较两个理论场景。为了问题的目的,我简化了案例。但基本上它是您典型的生产者消费者场景。 (我关注的是消费者)。 我有一个很大的Queue dataQueue我必须将其传输给多个客户端。 那么让我们
我有一个二元分类问题,标签 0 和 1(少数)存在巨大不平衡。由于测试集带有标签 1 的行太少,因此我将训练测试设置为至少 70-30 或 60-40,因此仍然有重要的观察结果。由于我没有过多地衡量准
我是一名优秀的程序员,十分优秀!