feat: 改进连接状态检查逻辑,优化文件传输和请求文件功能

This commit is contained in:
MatrixSeven
2025-09-19 18:19:25 +08:00
parent 08f9d50e66
commit 1e16e30681
4 changed files with 106 additions and 67 deletions

0
chuan-next/build-static.sh Normal file → Executable file
View File

View File

@@ -15,16 +15,23 @@ interface ConnectionStatusProps {
}
// 连接状态枚举
const getConnectionStatus = (currentRoom: { code: string; role: Role } | null) => {
const { getConnectState } = useReadConnectState(); // 确保状态管理器被初始化
const connection = getConnectState();
const isWebSocketConnected = connection?.isWebSocketConnected || false;
const isPeerConnected = connection?.isPeerConnected || false;
const isConnecting = connection?.isConnecting || false;
const error = connection?.error || null;
const currentConnectType = connection?.currentConnectType || 'webrtc';
const isJoinedRoom = connection?.isJoinedRoom || false;
const getConnectionStatus = (
currentRoom: { code: string; role: Role } | null,
connection: {
isWebSocketConnected: boolean;
isPeerConnected: boolean;
isConnecting: boolean;
error: string | null;
currentConnectType: 'webrtc' | 'websocket';
isJoinedRoom: boolean;
}
) => {
const isWebSocketConnected = connection.isWebSocketConnected;
const isPeerConnected = connection.isPeerConnected;
const isConnecting = connection.isConnecting;
const error = connection.error;
const currentConnectType = connection.currentConnectType;
const isJoinedRoom = connection.isJoinedRoom;
if (!currentRoom) {
return {
@@ -198,6 +205,10 @@ export function ConnectionStatus(props: ConnectionStatusProps) {
// 使用全局WebRTC状态
const webrtcState = useWebRTCStore();
// 获取连接状态
const { getConnectState } = useReadConnectState();
const connectionState = getConnectState();
// 创建connection对象以兼容现有代码
const connection = {
isWebSocketConnected: webrtcState.isWebSocketConnected,
@@ -205,6 +216,7 @@ export function ConnectionStatus(props: ConnectionStatusProps) {
isConnecting: webrtcState.isConnecting,
error: webrtcState.error,
currentConnectType: webrtcState.currentConnectType,
isJoinedRoom: connectionState?.isJoinedRoom || false,
};
const isConnected = webrtcState.isWebSocketConnected && webrtcState.isPeerConnected;
@@ -214,7 +226,7 @@ export function ConnectionStatus(props: ConnectionStatusProps) {
return <span className={cn('text-sm text-slate-600', className)}>{getConnectionStatusText(connection)}</span>;
}
const status = getConnectionStatus(currentRoom ?? null);
const status = getConnectionStatus(currentRoom ?? null, connection);
if (compact) {
return (

View File

@@ -385,19 +385,26 @@ export function useFileTransferBusiness(connection: IWebConnection) {
retryCount = 0
): Promise<boolean> => {
return new Promise((resolve) => {
// 主要检查数据通道状态,因为数据通道是文件传输的实际通道
// 改进数据传输前的连接状态检查
const channelState = connection.getConnectState();
if (channelState.state === 'closed') {
console.warn(`数据通道已关闭,停止发送文件块 ${chunkIndex}`);
const isChannelUsable =
channelState.state === 'open' ||
channelState.isDataChannelConnected ||
channelState.isPeerConnected ||
(channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket');
if (!isChannelUsable) {
console.warn(`数据块发送失败,传输通道不可用 ${chunkIndex}:`, {
state: channelState.state,
isDataChannelConnected: channelState.isDataChannelConnected,
isPeerConnected: channelState.isPeerConnected,
isWebSocketConnected: channelState.isWebSocketConnected,
currentConnectType: channelState.currentConnectType
});
resolve(false);
return;
}
// 如果连接暂时断开但数据通道可用,仍然可以尝试发送
if (!channelState.isConnected && channelState.state === 'connecting') {
console.warn(`WebRTC 连接暂时断开,但数据通道正在连接,继续尝试发送文件块 ${chunkIndex}`);
}
const chunkKey = `${fileId}-${chunkIndex}`;
// 设置确认回调
@@ -443,8 +450,27 @@ export function useFileTransferBusiness(connection: IWebConnection) {
// 安全发送文件
const sendFileSecure = useCallback(async (file: File, fileId?: string) => {
if (connection.getConnectState().state !== 'open') {
updateState({ error: '连接未就绪' });
// 改进连接状态检查 - 使用更全面的连接状态判断
const connectState = connection.getConnectState();
const isReadyToSend =
connectState.state === 'open' || // 数据通道已打开
connectState.isDataChannelConnected || // 数据通道已连接
connectState.isPeerConnected || // P2P连接已建立
(connectState.isWebSocketConnected && connectState.currentConnectType === 'websocket'); // WebSocket降级模式
console.log('发送文件前连接状态检查:', {
state: connectState.state,
isDataChannelConnected: connectState.isDataChannelConnected,
isPeerConnected: connectState.isPeerConnected,
isWebSocketConnected: connectState.isWebSocketConnected,
currentConnectType: connectState.currentConnectType,
isReadyToSend
});
if (!isReadyToSend) {
const errorMsg = `连接未就绪 - 状态: ${connectState.state}, 数据通道: ${connectState.isDataChannelConnected}, P2P: ${connectState.isPeerConnected}, WebSocket: ${connectState.isWebSocketConnected}`;
console.error(errorMsg);
updateState({ error: errorMsg });
return;
}
@@ -488,16 +514,23 @@ export function useFileTransferBusiness(connection: IWebConnection) {
let retryCount = 0;
while (!success && retryCount <= MAX_RETRIES) {
// 检查数据通道状态,这是文件传输的实际通道
// 改进传输过程中的连接状态检查
const channelState = connection.getConnectState();
if (channelState.state === 'closed') {
console.warn(`数据通道已关闭,停止文件传输`);
throw new Error('数据通道已关闭');
}
const isChannelUsable =
channelState.state === 'open' ||
channelState.isDataChannelConnected ||
channelState.isPeerConnected ||
(channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket');
// 如果连接暂时断开但数据通道可用,仍然可以尝试发送
if (!connection.getConnectState().isConnected && channelState.state === 'connecting') {
console.warn(`WebRTC 连接暂时断开,但数据通道正在连接,继续尝试发送文件块 ${chunkIndex}`);
if (!isChannelUsable) {
console.warn(`数据传输通道不可用,停止文件传输:`, {
state: channelState.state,
isDataChannelConnected: channelState.isDataChannelConnected,
isPeerConnected: channelState.isPeerConnected,
isWebSocketConnected: channelState.isWebSocketConnected,
currentConnectType: channelState.currentConnectType
});
throw new Error('数据传输通道不可用');
}
const start = chunkIndex * chunkSize;
@@ -596,26 +629,26 @@ export function useFileTransferBusiness(connection: IWebConnection) {
// 发送文件列表
const sendFileList = useCallback((fileList: FileInfo[]) => {
// 检查连接状态 - 优先检查数据通道状态,因为 P2P 连接可能已经建立但状态未及时更新
// 改进连接状态检查逻辑
const channelState = connection.getConnectState();
const peerConnected = channelState.isPeerConnected;
const dataChannelConnected = channelState.isDataChannelConnected;
const channelReadyState = channelState.state;
const isReadyToSend =
channelState.state === 'open' ||
channelState.isDataChannelConnected ||
channelState.isPeerConnected ||
(channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket') ||
channelState.isConnected;
console.log('发送文件列表检查:', {
channelState,
peerConnected,
dataChannelConnected,
channelReadyState,
state: channelState.state,
isDataChannelConnected: channelState.isDataChannelConnected,
isPeerConnected: channelState.isPeerConnected,
isWebSocketConnected: channelState.isWebSocketConnected,
currentConnectType: channelState.currentConnectType,
isConnected: channelState.isConnected,
isReadyToSend,
fileListLength: fileList.length
});
// 使用更宽松的条件检查连接状态
const isReadyToSend = channelReadyState === 'open' ||
dataChannelConnected ||
peerConnected ||
channelState.isConnected;
if (isReadyToSend) {
console.log('发送文件列表:', fileList.map(f => f.name));
@@ -629,42 +662,36 @@ export function useFileTransferBusiness(connection: IWebConnection) {
// 不立即重试,让上层逻辑处理重试
}
} else {
console.log('连接未就绪,等待连接后再发送文件列表:', {
channelReadyState,
dataChannelConnected,
peerConnected,
isConnected: channelState.isConnected
});
console.log('连接未就绪,等待连接后再发送文件列表');
}
}, [connection]);
// 请求文件
const requestFile = useCallback((fileId: string, fileName: string) => {
const channelState = connection.getConnectState();
const isChannelOpen = channelState.state === 'open';
const isDataChannelConnected = channelState.isDataChannelConnected;
const isPeerConnected = channelState.isPeerConnected;
const isConnected = channelState.isConnected;
// 统一的连接状态检查逻辑
const isReadyToRequest =
channelState.state === 'open' ||
channelState.isDataChannelConnected ||
channelState.isPeerConnected ||
(channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket') ||
channelState.isConnected;
console.log('请求文件前检查连接状态:', {
fileName,
fileId,
isChannelOpen,
isDataChannelConnected,
isPeerConnected,
isConnected
state: channelState.state,
isDataChannelConnected: channelState.isDataChannelConnected,
isPeerConnected: channelState.isPeerConnected,
isWebSocketConnected: channelState.isWebSocketConnected,
currentConnectType: channelState.currentConnectType,
isConnected: channelState.isConnected,
isReadyToRequest
});
// 使用更宽松的条件检查连接状态
const isReadyToRequest = isChannelOpen || isDataChannelConnected || isPeerConnected || isConnected;
if (!isReadyToRequest) {
console.error('数据通道未准备就绪,无法请求文件:', {
isChannelOpen,
isDataChannelConnected,
isPeerConnected,
isConnected
});
console.error('数据通道未准备就绪,无法请求文件');
return;
}

View File

@@ -26,7 +26,7 @@ const getCurrentBaseUrl = () => {
// 动态获取 WebSocket URL - 总是在客户端运行时计算
const getCurrentWsUrl = () => {
return "ws://192.168.1.120:8080"
// return "ws://192.168.1.120:8080"
if (typeof window !== 'undefined') {
// 检查是否是 Next.js 开发服务器(端口 3000 或 3001
const isNextDevServer = window.location.hostname === 'localhost' &&