我正在 ASP.NET + React 上构建扑克游戏,并使用 signalR 进行实时通信。 大多数时候它工作正常。 但有时在客户端,我无法从服务器端接收事件,所以从那一刻起,就无法与其他玩家同步。 刷新后,它再次工作。 我找不到问题是什么,什么时候没有收到。
useEffect(() => {
const startConnection = async () => {
let newConnection = await MainV2.startConnectionWithUserIdentity(user.Id);
LogRocket.log("Connected to SignalR", newConnection.connectionId);
/* newConnection.onclose(() => {
newConnection.start();
}); */
setConnection(newConnection);
};
startConnection();
}, [user]);
MainV2.startConnectionWithUserIdentity 函数就像
const connection = new HubConnectionBuilder()
.withUrl(GetFullURL(`GameClass?UserIdentity=${UniqueId}`))
.withAutomaticReconnect()
.build();
if (connection.state === HubConnectionState.Connected) return;
await connection.start();
这是连接到集线器的代码,下面是我将事件附加到连接的代码。
useEffect(() => {
if (connection.state === HubConnectionState.Connected) {
//.....
connection.on("OtherPlayerDisconnected", (UserId, UserName) => {
OtherPlayerDisconnected(UserId, UserName);
});
connection.on("ReceiveHashV1", () => {
SendRequest({
url: "GameV2/_GetGameHash",
method: "post",
data: { GameCode },
}).then((result) => {
LogRocket.log("Received GameHash on Game: " + GameCode, {
GameHash: result.data,
});
setGameHash(result.data);
});
});
setConnection(connection);
}
return () => {
if (connection.state === HubConnectionState.Connected) {
connection.off("ReceiveHashV1");
connection.off("OtherPlayerDisconnected");
connection.off("ReceiveEndHandSummary");
connection.off("ReceiveEndGameSummary");
connection.off("ReceiveCancelHandNotification");
connection.off("RemovedNotification");
connection.off("ReceiveMessage");
setConnection(connection);
}
};
}, [
connection.connectionId,
]);
我找不到它在哪里没有收到事件所以什么也做不了。
public class GameClass : Hub
{
public static List<string> ConnectionIds = new List<string>();
public static bool IsBusy = false;
private static readonly ConcurrentDictionary<string, string> Users = new ConcurrentDictionary<string, string>();
private readonly DBCardGameContext _dbCardGameContext;
public GameClass(DBCardGameContext dbCardGameContext)
{
_dbCardGameContext = dbCardGameContext;
}
/*
Send "ReceiveMessage" to all clients.
*/
public int SendMessage(string user, string message)
{
try
{
if (IsBusy == false)
{
IsBusy = true;
var val1 = Context.ConnectionId;
var val2 = Context.User;
var val3 = Clients.Caller;
ConnectionIds.Add(user + "===" + message);
Clients.All.SendAsync("ReceiveMessage", user, message);
return 1;
}
else
{
return 0;
}
}
catch (Exception ex)
{
return -1;
}
}
/*
Send "ReciveNotification" to all Clients.
@param
gamecode: GameCode that will receive notfication.
playerid: PlayerId that send notficiation.
notificationmessage: message
*/
public async Task SendNotification(string gamecode, string playerid, string notificationmessage)
{
var val1 = Context.ConnectionId;
var val2 = Context.User;
var val3 = Clients.Caller;
// ConnectionIds.Add(user + "===" + message);
await Clients.All.SendAsync("ReceiveNotification", gamecode, playerid, notificationmessage);
}
public async Task GameLog(string GameCode, string ActionName, string PlayerUniqueId, string PlayerName)
{
}
/*
SendRemoveNotification
*/
public async Task SendRemoveNotification(string GameCode, string UserId)
{
var player = await _dbCardGameContext.Player.Where(x => x.GameCode == GameCode && x.PlayerUniqueId == UserId).FirstOrDefaultAsync();
var val1 = Context.ConnectionId;
await Clients.Client(player.SignalRconnectionId).SendAsync("RemovedNotification");
}
/*
Send "ReceiveEndGameSummary"
@param
gamecode: GameCode that send notification
*/
public async Task SendEndGameSummary(string gamecode)
{
var val1 = Context.ConnectionId;
var val2 = Context.User;
var val3 = Clients.Caller;
// ConnectionIds.Add(user + "===" + message);
await Clients.All.SendAsync("ReceiveEndGameSummary", gamecode);
}
/*
Send "ReceiveEndHandSummary"
@param
gamecode: GameCode that send notification
*/
public async Task SendEndHandSummary(string gamecode)
{
var val1 = Context.ConnectionId;
var val2 = Context.User;
var val3 = Clients.Caller;
// ConnectionIds.Add(user + "===" + message);
await Clients.All.SendAsync("ReceiveEndHandSummary", gamecode);
}
//same as SendMessage
public async Task SendMessage2(string user, string message, string test)
{
var val1 = Context.ConnectionId;
var val2 = Context.User;
var val3 = Clients.Caller;
ConnectionIds.Add(user + "===" + message);
JavaScriptSerializer js = new JavaScriptSerializer();
string jsonData = js.Serialize(ConnectionIds); // {"Name":"C-
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
//same as SendMessage
public async Task ReceiveOnLoad(string user, string message)
{
var val1 = Context.ConnectionId;
var val2 = Context.User;
var val3 = Clients.Caller;
// string val1 = "";
JavaScriptSerializer js = new JavaScriptSerializer();
string jsonData = js.Serialize(ConnectionIds); // {"Name":"C-
await Clients.All.SendAsync("ReceiveMessage", user, jsonData);
}
// when you connect to GameClass Hub, this function invoked.
public override Task OnConnectedAsync()
{
HttpContext httpContext = Context.GetHttpContext();
//Get PlayerUniqueId of connecting user
/*var customQuerystring = httpContext.Request.QueryString.Value.Split("&").FirstOrDefault().Split("=").LastOrDefault();
if (customQuerystring != null)
{
//If player already added to Database, just change player's Modified time and isConnected = true, SignalRconnectionId as new connectionId.
var player = _dbCardGameContext.Player.Where(x => x.PlayerUniqueId == customQuerystring).FirstOrDefault();
if (player != null)
{
player.LastActionTime = DateTime.Now;
player.Modified = DateTime.Now;
player.SignalRconnectionId = Context.ConnectionId;
player.IsConnected = true;
_dbCardGameContext.SaveChanges();
}
//If not exist, Add new player
else
{
_dbCardGameContext.Player.Add(new Player() { Created = DateTime.Now, IsConnected = true, LastActionTime = DateTime.Now, PlayerUniqueId = customQuerystring, SignalRconnectionId = Context.ConnectionId });
_dbCardGameContext.SaveChanges();
}
}*/
return base.OnConnectedAsync();
}
//when you close connection, this function invokes.
public override Task OnDisconnectedAsync(Exception exception)
{
Console.Out.WriteLine(Context.ConnectionId);
try
{
//Get disconnectedplayer
var disconnectedplayer = _dbCardGameContext.Player.Where(x => x.SignalRconnectionId == Context.ConnectionId).FirstOrDefault();
if (disconnectedplayer != null)
{
//If disconnectedplayer currently join game and active, set him deactive.
if (disconnectedplayer.GameCode != "" && disconnectedplayer.GameCode != null)
{
disconnectedplayer.IsConnected = false;
disconnectedplayer.IsActive = false;
disconnectedplayer.IsCurrent = false;
disconnectedplayer.IsDealer = false;
disconnectedplayer.IsFolded = false;
_dbCardGameContext.SaveChanges();
//all other players in the same game
var allrelatedplayers = _dbCardGameContext.Player.Where(x => x.GameCode == disconnectedplayer.GameCode && x.SignalRconnectionId != Context.ConnectionId).ToList();
foreach (var ar in allrelatedplayers)
{
//Send "OtherPlayerDisconnected" msg.
Clients.Client(ar.SignalRconnectionId).SendAsync("OtherPlayerDisconnected", disconnectedplayer.PlayerUniqueId, disconnectedplayer.UserName);
}
}
}
}
catch (Exception ex)
{
}
Task tsk = new Task(() =>
{
});
return tsk;
}
}