fix: 优化网页端不能连接的问题
This commit is contained in:
@@ -18,6 +18,8 @@ export class SignalingClient {
|
||||
this.ws.onopen = () => {
|
||||
this.register();
|
||||
this.onConnected && this.onConnected();
|
||||
// 启动心跳保活:每 25 秒发送 ping,防止中间代理或服务器因空闲超时断开连接
|
||||
this._startHeartbeat();
|
||||
};
|
||||
this.ws.onmessage = (ev) => {
|
||||
let msg;
|
||||
@@ -28,13 +30,38 @@ export class SignalingClient {
|
||||
}
|
||||
this.onMessage && this.onMessage(msg);
|
||||
};
|
||||
this.ws.onclose = () => this.onDisconnected && this.onDisconnected();
|
||||
this.ws.onerror = (e) => this.onError && this.onError(e?.message || 'WebSocket 错误');
|
||||
this.ws.onclose = (ev) => {
|
||||
// 记录关闭码和原因,便于诊断断连根因:
|
||||
// 1000 = 正常关闭, 1001 = 离开, 1006 = 异常断开(无 close frame)
|
||||
// 1009 = 消息过大, 1011 = 服务端异常
|
||||
console.warn('[信令] WebSocket 已关闭 code=%d reason=%s wasClean=%s',
|
||||
ev.code, ev.reason || '(无)', ev.wasClean);
|
||||
this._stopHeartbeat();
|
||||
this.onDisconnected && this.onDisconnected(ev.code, ev.reason);
|
||||
};
|
||||
this.ws.onerror = (e) => {
|
||||
console.error('[信令] WebSocket 错误', e);
|
||||
this.onError && this.onError(e?.message || 'WebSocket 错误');
|
||||
};
|
||||
} catch (e) {
|
||||
this.onError && this.onError(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
_startHeartbeat() {
|
||||
this._stopHeartbeat();
|
||||
this._heartbeatTimer = setInterval(() => {
|
||||
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
||||
// 发送轻量级 ping 消息,保持连接活跃(服务端会忽略未知类型消息)
|
||||
try { this.ws.send(JSON.stringify({ type: 'PING' })); } catch { /* ignore */ }
|
||||
}
|
||||
}, 25000);
|
||||
}
|
||||
|
||||
_stopHeartbeat() {
|
||||
if (this._heartbeatTimer) { clearInterval(this._heartbeatTimer); this._heartbeatTimer = null; }
|
||||
}
|
||||
|
||||
register() {
|
||||
this.send({
|
||||
type: 'REGISTER',
|
||||
@@ -79,6 +106,7 @@ export class SignalingClient {
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this._stopHeartbeat();
|
||||
if (this.ws) {
|
||||
this.ws.close();
|
||||
this.ws = null;
|
||||
|
||||
@@ -13,9 +13,9 @@ export const DEFAULT_ICE_SERVERS = [
|
||||
// { urls: 'turn:192.168.100.224:3478?transport=tcp', username: 'tt', credential: 'fht' },
|
||||
{ urls: 'stun:175.178.213.60:3478' },
|
||||
// { urls: 'stun:192.168.5.224:3478' },
|
||||
// { urls: 'stun:stun.l.google.com:19302' },
|
||||
// { urls: 'stun:stun1.l.google.com:19302' },
|
||||
// { urls: 'stun:stun2.l.google.com:19302' },
|
||||
// { urls: 'stun:stun.l.google.com:19302' },
|
||||
// { urls: 'stun:stun1.l.google.com:19302' },
|
||||
// { urls: 'stun:stun2.l.google.com:19302' },
|
||||
];
|
||||
|
||||
export const store = reactive({
|
||||
@@ -128,21 +128,30 @@ export async function connectToDevice(targetId) {
|
||||
|
||||
if (webrtc) { await webrtc.close(); webrtc = null; }
|
||||
|
||||
webrtc = new WebRtcController({
|
||||
iceServers: store.iceServers,
|
||||
deviceId: store.deviceId,
|
||||
targetDeviceId: targetId,
|
||||
signaling,
|
||||
onIceState: (s) => {
|
||||
if (s === 'connected') { store.rtcConnected = true; store.statusText = '已连接,可远程控制'; }
|
||||
else if (s === 'disconnected' || s === 'failed') { store.rtcConnected = false; store.statusText = '连接已断开'; }
|
||||
},
|
||||
onDataChannelState: (open) => { store.dataChannelOpen = open; },
|
||||
onStream: (stream) => { store.remoteStream = markRaw(stream); },
|
||||
onStats: (stats) => { store.stats = stats; },
|
||||
onError: (msg) => { if (msg) store.error = msg; },
|
||||
});
|
||||
await webrtc.createOffer();
|
||||
try {
|
||||
webrtc = new WebRtcController({
|
||||
iceServers: store.iceServers,
|
||||
deviceId: store.deviceId,
|
||||
targetDeviceId: targetId,
|
||||
signaling,
|
||||
onIceState: (s) => {
|
||||
if (s === 'connected') { store.rtcConnected = true; store.statusText = '已连接,可远程控制'; }
|
||||
else if (s === 'disconnected' || s === 'failed') { store.rtcConnected = false; store.statusText = '连接已断开'; }
|
||||
},
|
||||
onDataChannelState: (open) => { store.dataChannelOpen = open; },
|
||||
onStream: (stream) => { store.remoteStream = markRaw(stream); },
|
||||
onStats: (stats) => { store.stats = stats; },
|
||||
onError: (msg) => { if (msg) store.error = msg; },
|
||||
});
|
||||
await webrtc.createOffer();
|
||||
} catch (e) {
|
||||
// 捕获 createOffer 阶段的所有异常,避免未处理的 Promise 拒绝导致浏览器中断脚本执行、
|
||||
// 间接影响 WebSocket 信令连接的存活。
|
||||
console.error('[connectToDevice] 创建 Offer 失败:', e);
|
||||
store.error = '创建连接失败: ' + (e?.message || e);
|
||||
store.statusText = '连接失败';
|
||||
if (webrtc) { await webrtc.close(); webrtc = null; }
|
||||
}
|
||||
}
|
||||
|
||||
export async function disconnectDevice() {
|
||||
|
||||
Reference in New Issue
Block a user