This commit is contained in:
2026-07-17 17:50:31 +08:00
parent efce942e52
commit 287ece9dc8
14 changed files with 229 additions and 86 deletions
+84 -45
View File
@@ -22,6 +22,13 @@ namespace Assets.MyGame.Scripts.Net
{
private readonly Dictionary<SocketType, WebSocket> sockets = new();
private readonly Dictionary<SocketType, string> socketPaths = new();
private readonly Dictionary<SocketType, string> socketUrls = new();
private readonly Dictionary<SocketType, Action> handshakeActions = new();
private readonly HashSet<SocketType> handshakeCompleted = new();
private readonly HashSet<SocketType> reconnecting = new();
private readonly HashSet<SocketType> manualClosing = new();
private float nextHeartbeatTime;
private const float HeartbeatIntervalSeconds = 20f;
//private const string baseUrl = "ws://game5241.wzaxr.top";
#if UNITY_EDITOR
@@ -33,7 +40,7 @@ namespace Assets.MyGame.Scripts.Net
private const string baseUrl = "ws://8.137.163.153";
#endif
public bool isGame=false;
public bool isGame = false;
protected override void Awake()
{
base.Awake();
@@ -43,12 +50,26 @@ namespace Assets.MyGame.Scripts.Net
socketPaths[SocketType.login] = "/loginhub";
socketPaths[SocketType.chess] = "/chessgamehub";
socketPaths[SocketType.customer] = "/customerHub";
nextHeartbeatTime = Time.realtimeSinceStartup + HeartbeatIntervalSeconds;
}
private void Update()
{
if (Time.realtimeSinceStartup < nextHeartbeatTime)
return;
nextHeartbeatTime = Time.realtimeSinceStartup + HeartbeatIntervalSeconds;
foreach (var pair in sockets)
{
if (pair.Value != null && pair.Value.IsOpen && handshakeCompleted.Contains(pair.Key))
pair.Value.Send("{\"type\":6}\u001e");
}
}
/// <summary>
/// 创建或返回已存在的 WebSocket
/// </summary>
public WebSocket Connect(SocketType type,Action action=null)
public WebSocket Connect(SocketType type, Action action = null)
{
return Connect(type, null, action);
}
@@ -73,7 +94,6 @@ namespace Assets.MyGame.Scripts.Net
case SocketType.login:
break;
case SocketType.room:
WebSocketSendList.JoinRoom("11109", GameManager.Instance.user.id, 1);
break;
case SocketType.game:
break;
@@ -94,6 +114,8 @@ namespace Assets.MyGame.Scripts.Net
// 未指定 url 时用默认 baseUrl + socketPaths
if (string.IsNullOrEmpty(url))
url = baseUrl + socketPaths[type];
socketUrls[type] = url;
handshakeActions[type] = action;
var ws = new WebSocket(new Uri(url));
sockets[type] = ws;
// 事件绑定
@@ -104,31 +126,10 @@ namespace Assets.MyGame.Scripts.Net
#endif
web.Send("{\"protocol\":\"json\",\"version\":1}\u001e ");
switch (type)
{
case SocketType.login:
WebSocketSendList.Bind(GameManager.Instance.user.id);
break;
case SocketType.room:
break;
case SocketType.game:
break;
case SocketType.chess:
//WebSocketSendList.GetRoomListChineseChess(1);
//UIManager.Instance.Get<ChineseChessMainPanel>(UIPanel.MainGamePanelZGXQ).subUIManager.ShowAsync(UIPanel.ZGXQDistrict);
UIManager.Instance.ShowAsync(UIPanel.MainGamePanelZGXQ);
break;
case SocketType.customer:
break;
default:
break;
}
if (action != null)
action?.Invoke();
reconnecting.Remove(type);
handshakeCompleted.Remove(type);
// SignalR 握手完成前不能发送 Bind、JoinRoom 等 Hub 调用。
web.Send("{\"protocol\":\"json\",\"version\":1}\u001e");
};
ws.OnClosed += (web, code, reason) =>
@@ -138,10 +139,17 @@ namespace Assets.MyGame.Scripts.Net
#endif
handshakeCompleted.Remove(type);
if (sockets.TryGetValue(type, out var current) && ReferenceEquals(current, web))
sockets.Remove(type);
if (manualClosing.Remove(type))
return;
// 自动重连
switch (type)
{
case SocketType.login:
StartReconnect(type);
break;
case SocketType.room:
break;
@@ -151,15 +159,15 @@ namespace Assets.MyGame.Scripts.Net
int sitpos = 0;
foreach (var item in GameManager.Instance.gameData.currRoomData.players)
{
if (item.userId==GameManager.Instance.user.id)
if (item.userId == GameManager.Instance.user.id)
{
sitpos = item.position; break;
}
}
StartCoroutine(Reconnect(type, () =>
StartReconnect(type, () =>
{
WebSocketSendList.JoinRoom(GameManager.Instance.gameData.currRoomData.roomId, GameManager.Instance.user.id, sitpos);
}));
});
}
break;
case SocketType.chess:
@@ -169,17 +177,8 @@ namespace Assets.MyGame.Scripts.Net
default:
break;
}
};
ws.OnClosed += (web, code, message) =>
{
#if UNITY_EDITOR
Debug.LogError($"[WebSocket] {type} 错误{code}: {message}");
#endif
};
ws.OnMessage += (web, msg) =>
@@ -214,7 +213,7 @@ namespace Assets.MyGame.Scripts.Net
{
#if UNITY_EDITOR
Debug.LogWarning($"[WebSocket] {type} 未连接,无法发送消息");
Debug.LogWarning($"[WebSocket] {type} 未连接,无法发送消息" + msg);
#endif
UIManager.Instance.ShowBoardError($"[WebSocket] {type} 未连接,无法发送消息");
@@ -228,6 +227,8 @@ namespace Assets.MyGame.Scripts.Net
{
if (sockets.TryGetValue(type, out var ws))
{
manualClosing.Add(type);
handshakeCompleted.Remove(type);
ws.Close(WebSocketStatusCodes.NormalClosure, "正常关闭"); // 或者 CloseStatusCode.Normal
//ws.Close();
sockets.Remove(type);
@@ -248,7 +249,14 @@ namespace Assets.MyGame.Scripts.Net
/// <summary>
/// 自动重连
/// </summary>
private System.Collections.IEnumerator Reconnect(SocketType type,Action action=null)
private void StartReconnect(SocketType type, Action action = null)
{
if (!reconnecting.Add(type))
return;
StartCoroutine(Reconnect(type, action));
}
private System.Collections.IEnumerator Reconnect(SocketType type, Action action = null)
{
#if UNITY_EDITOR
@@ -256,7 +264,36 @@ namespace Assets.MyGame.Scripts.Net
#endif
yield return new WaitForSeconds(3f);
Connect(type,action);
if (manualClosing.Contains(type))
{
reconnecting.Remove(type);
yield break;
}
socketUrls.TryGetValue(type, out var url);
Connect(type, url, action);
}
private void OnHandshakeCompleted(SocketType type)
{
if (!handshakeCompleted.Add(type))
return;
switch (type)
{
case SocketType.login:
WebSocketSendList.Bind(GameManager.Instance.user.id);
break;
case SocketType.chess:
UIManager.Instance.ShowAsync(UIPanel.MainGamePanelZGXQ);
break;
}
if (handshakeActions.TryGetValue(type, out var action) && action != null)
{
handshakeActions[type] = null;
action.Invoke();
}
}
/// <summary>
@@ -264,11 +301,13 @@ namespace Assets.MyGame.Scripts.Net
/// </summary>
private void OnDestroy()
{
foreach (var ws in sockets.Values)
foreach (var type in new List<SocketType>(sockets.Keys))
manualClosing.Add(type);
foreach (var ws in new List<WebSocket>(sockets.Values))
{
ws.Close();
}
sockets.Clear();
}
}
}
}