Android WebView应用WebSocket本地/公网IP自动切换及JS合并咨询
实现WebSocket本地/公网地址自动切换并合并JS逻辑
嘿,这个需求很实用!咱们可以通过先尝试本地连接,失败后自动 fallback 到公网地址的方式,把两个JS逻辑合并成一个,而且不用手动切换。下面是具体的实现方案:
核心思路
- 定义本地和公网两个WebSocket地址常量,方便后续维护
- 封装通用的连接函数,复用WebSocket的创建、事件绑定逻辑
- 优先尝试连接本地地址,若连接失败(或超时),自动切换到公网地址重试
- 加入失败重试限制,避免无限循环发起连接请求
完整合并后的JS代码
// 定义本地和公网WebSocket地址
const LOCAL_WS_URL = "ws://192.168.1.40:81/";
const PUBLIC_WS_URL = "ws://xxxxxx.ddns.net:81/";
let connection;
let connectionAttempts = 0;
const MAX_ATTEMPTS = 2; // 最多尝试本地+公网两次
// 通用WebSocket连接函数
function connectWebSocket(targetUrl) {
console.log(`正在尝试连接: ${targetUrl}`);
connection = new WebSocket(targetUrl);
// 连接成功回调
connection.onopen = function () {
console.log(`成功连接到 ${targetUrl}`);
connection.send('Websocket funcionando!' + new Date());
connectionAttempts = 0; // 重置尝试次数
};
// 连接错误回调
connection.onerror = function (error) {
console.log(`WebSocket 连接错误 (${targetUrl}):`, error);
handleConnectionFailure();
};
// 意外关闭连接时触发切换
connection.onclose = function (event) {
if (!event.wasClean) {
console.log(`连接意外断开 (${targetUrl}),准备切换地址重试`);
handleConnectionFailure();
}
};
// 接收服务器消息回调
connection.onmessage = function (e) {
console.log('Server:', e.data);
};
// 超时检测:5秒内未成功连接则视为失败
setTimeout(() => {
if (connection.readyState !== WebSocket.OPEN) {
console.log(`连接超时 (${targetUrl})`);
connection.close();
handleConnectionFailure();
}
}, 5000);
}
// 处理连接失败后的逻辑
function handleConnectionFailure() {
connectionAttempts++;
if (connectionAttempts < MAX_ATTEMPTS) {
// 第一次失败切换到公网,第二次失败可根据需求调整
const nextUrl = connectionAttempts === 1 ? PUBLIC_WS_URL : LOCAL_WS_URL;
setTimeout(() => connectWebSocket(nextUrl), 1000); // 延迟1秒重试,避免频繁请求
} else {
console.log("本地和公网连接均失败,请检查服务器状态或网络");
connectionAttempts = 0; // 重置次数,方便后续手动重试
}
}
// 初始化:优先尝试本地连接
connectWebSocket(LOCAL_WS_URL);
代码关键点解释
- 地址常量化:把两个地址抽成常量,后续修改时只需改一处,更易维护
- 逻辑复用:用通用连接函数封装重复的WebSocket创建、事件绑定代码,减少冗余
- 超时处理:添加5秒超时逻辑,避免连接一直处于pending状态无法触发切换
- 重试限制:最多尝试两次连接,防止无限循环请求服务器
- 状态重置:连接成功或全部失败后重置尝试次数,保证后续重试逻辑正常
额外优化建议
- 可以添加手动切换按钮,让用户在需要时强制切换地址:
// 手动切换到公网地址 function switchToPublic() { if (connection) connection.close(); connectionAttempts = 0; connectWebSocket(PUBLIC_WS_URL); } // 手动切换到本地地址 function switchToLocal() { if (connection) connection.close(); connectionAttempts = 0; connectWebSocket(LOCAL_WS_URL); } - 可以用
localStorage缓存上次成功连接的地址,下次初始化时优先使用,提升用户体验
内容的提问来源于stack exchange,提问作者Khales Naim




