Files
whale-town-end/full_diagnosis.js
moyin 38f9f81b6c test:添加WebSocket连接诊断和测试工具集
- test_zulip.js: Zulip集成功能的端到端测试脚本
- full_diagnosis.js: 全面的WebSocket连接诊断工具
- test_protocol_difference.js: 不同协议(ws/wss/http/https)的对比测试
- test_redirect_and_websocket.js: HTTP重定向和WebSocket升级测试
- test_websocket_handshake_redirect.js: WebSocket握手重定向机制验证
- websocket_with_redirect_support.js: 支持重定向的WebSocket连接实现

提供完整的WebSocket连接问题诊断和解决方案
2026-01-05 11:16:52 +08:00

311 lines
8.9 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const io = require('socket.io-client');
const https = require('https');
const http = require('http');
console.log('🔍 全面WebSocket连接诊断');
console.log('='.repeat(60));
// 1. 测试基础网络连接
async function testBasicConnection() {
console.log('\n1⃣ 测试基础HTTPS连接...');
return new Promise((resolve) => {
const options = {
hostname: 'whaletownend.xinghangee.icu',
port: 443,
path: '/',
method: 'GET',
timeout: 10000
};
const req = https.request(options, (res) => {
console.log(`✅ HTTPS连接成功 - 状态码: ${res.statusCode}`);
console.log(`📋 服务器: ${res.headers.server || '未知'}`);
resolve({ success: true, statusCode: res.statusCode });
});
req.on('error', (error) => {
console.log(`❌ HTTPS连接失败: ${error.message}`);
resolve({ success: false, error: error.message });
});
req.on('timeout', () => {
console.log('❌ HTTPS连接超时');
req.destroy();
resolve({ success: false, error: 'timeout' });
});
req.end();
});
}
// 2. 测试本地服务器
async function testLocalServer() {
console.log('\n2⃣ 测试本地服务器...');
const testPaths = [
'http://localhost:3000/',
'http://localhost:3000/socket.io/?EIO=4&transport=polling'
];
for (const url of testPaths) {
console.log(`🧪 测试: ${url}`);
await new Promise((resolve) => {
const urlObj = new URL(url);
const options = {
hostname: urlObj.hostname,
port: urlObj.port,
path: urlObj.pathname + urlObj.search,
method: 'GET',
timeout: 5000
};
const req = http.request(options, (res) => {
console.log(` 状态码: ${res.statusCode}`);
if (res.statusCode === 200) {
console.log(' ✅ 本地服务器正常');
} else {
console.log(` ⚠️ 本地服务器响应: ${res.statusCode}`);
}
resolve();
});
req.on('error', (error) => {
console.log(` ❌ 本地服务器连接失败: ${error.message}`);
resolve();
});
req.on('timeout', () => {
console.log(' ❌ 本地服务器超时');
req.destroy();
resolve();
});
req.end();
});
}
}
// 3. 测试远程Socket.IO路径
async function testRemoteSocketIO() {
console.log('\n3⃣ 测试远程Socket.IO路径...');
const testPaths = [
'/socket.io/?EIO=4&transport=polling',
'/game/socket.io/?EIO=4&transport=polling',
'/socket.io/?transport=polling',
'/api/socket.io/?EIO=4&transport=polling'
];
const results = [];
for (const path of testPaths) {
console.log(`🧪 测试路径: ${path}`);
const result = await new Promise((resolve) => {
const options = {
hostname: 'whaletownend.xinghangee.icu',
port: 443,
path: path,
method: 'GET',
timeout: 8000,
headers: {
'User-Agent': 'socket.io-diagnosis'
}
};
const req = https.request(options, (res) => {
console.log(` 状态码: ${res.statusCode}`);
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
if (res.statusCode === 200) {
console.log(' ✅ 路径可用');
console.log(` 📄 响应: ${data.substring(0, 50)}...`);
} else {
console.log(` ❌ 路径不可用: ${res.statusCode}`);
}
resolve({ path, statusCode: res.statusCode, success: res.statusCode === 200 });
});
});
req.on('error', (error) => {
console.log(` ❌ 请求失败: ${error.message}`);
resolve({ path, error: error.message, success: false });
});
req.on('timeout', () => {
console.log(' ❌ 请求超时');
req.destroy();
resolve({ path, error: 'timeout', success: false });
});
req.end();
});
results.push(result);
}
return results;
}
// 4. 测试Socket.IO客户端连接
async function testSocketIOClient() {
console.log('\n4⃣ 测试Socket.IO客户端连接...');
const configs = [
{
name: 'HTTPS + 所有传输方式',
url: 'https://whaletownend.xinghangee.icu',
options: { transports: ['websocket', 'polling'], timeout: 10000 }
},
{
name: 'HTTPS + 仅Polling',
url: 'https://whaletownend.xinghangee.icu',
options: { transports: ['polling'], timeout: 10000 }
},
{
name: 'HTTPS + /game namespace',
url: 'https://whaletownend.xinghangee.icu/game',
options: { transports: ['polling'], timeout: 10000 }
}
];
const results = [];
for (const config of configs) {
console.log(`🧪 测试: ${config.name}`);
console.log(` URL: ${config.url}`);
const result = await new Promise((resolve) => {
const socket = io(config.url, config.options);
let resolved = false;
const timeout = setTimeout(() => {
if (!resolved) {
resolved = true;
socket.disconnect();
console.log(' ❌ 连接超时');
resolve({ success: false, error: 'timeout' });
}
}, config.options.timeout);
socket.on('connect', () => {
if (!resolved) {
resolved = true;
clearTimeout(timeout);
console.log(' ✅ 连接成功');
console.log(` 📡 Socket ID: ${socket.id}`);
console.log(` 🚀 传输方式: ${socket.io.engine.transport.name}`);
socket.disconnect();
resolve({ success: true, transport: socket.io.engine.transport.name });
}
});
socket.on('connect_error', (error) => {
if (!resolved) {
resolved = true;
clearTimeout(timeout);
console.log(` ❌ 连接失败: ${error.message}`);
resolve({ success: false, error: error.message });
}
});
});
results.push({ config: config.name, ...result });
// 等待1秒再测试下一个
await new Promise(resolve => setTimeout(resolve, 1000));
}
return results;
}
// 5. 检查DNS解析
async function testDNS() {
console.log('\n5⃣ 检查DNS解析...');
const dns = require('dns');
return new Promise((resolve) => {
dns.lookup('whaletownend.xinghangee.icu', (err, address, family) => {
if (err) {
console.log(`❌ DNS解析失败: ${err.message}`);
resolve({ success: false, error: err.message });
} else {
console.log(`✅ DNS解析成功: ${address} (IPv${family})`);
resolve({ success: true, address, family });
}
});
});
}
// 主诊断函数
async function runFullDiagnosis() {
console.log('开始全面诊断...\n');
try {
const dnsResult = await testDNS();
const basicResult = await testBasicConnection();
await testLocalServer();
const socketIOPaths = await testRemoteSocketIO();
const clientResults = await testSocketIOClient();
console.log('\n' + '='.repeat(60));
console.log('📊 诊断结果汇总');
console.log('='.repeat(60));
console.log(`1. DNS解析: ${dnsResult.success ? '✅ 正常' : '❌ 失败'}`);
if (dnsResult.address) {
console.log(` IP地址: ${dnsResult.address}`);
}
console.log(`2. HTTPS连接: ${basicResult.success ? '✅ 正常' : '❌ 失败'}`);
if (basicResult.error) {
console.log(` 错误: ${basicResult.error}`);
}
const workingPaths = socketIOPaths.filter(r => r.success);
console.log(`3. Socket.IO路径: ${workingPaths.length}/${socketIOPaths.length} 个可用`);
workingPaths.forEach(p => {
console.log(`${p.path}`);
});
const workingClients = clientResults.filter(r => r.success);
console.log(`4. Socket.IO客户端: ${workingClients.length}/${clientResults.length} 个成功`);
workingClients.forEach(c => {
console.log(`${c.config} (${c.transport})`);
});
console.log('\n💡 建议:');
if (!dnsResult.success) {
console.log('❌ DNS解析失败 - 检查域名配置');
} else if (!basicResult.success) {
console.log('❌ 基础HTTPS连接失败 - 检查服务器状态和防火墙');
} else if (workingPaths.length === 0) {
console.log('❌ 所有Socket.IO路径都不可用 - 检查nginx配置和后端服务');
} else if (workingClients.length === 0) {
console.log('❌ Socket.IO客户端无法连接 - 可能是CORS或协议问题');
} else {
console.log('✅ 部分功能正常 - 使用可用的配置继续开发');
if (workingClients.length > 0) {
const bestConfig = workingClients.find(c => c.transport === 'websocket') || workingClients[0];
console.log(`💡 推荐使用: ${bestConfig.config}`);
}
}
} catch (error) {
console.error('诊断过程中发生错误:', error);
}
process.exit(0);
}
runFullDiagnosis();