fix desync & try to fix delay
This commit is contained in:
parent
b077097a33
commit
dc893baf94
5 changed files with 78 additions and 3 deletions
|
|
@ -14,9 +14,44 @@ public class Program
|
|||
// Entries are pruned in the 1s loop below.
|
||||
public static ConcurrentDictionary<string, (int count, long resetAt)> UsersListLimits = new ();
|
||||
|
||||
// Sesja bez ODBIERANEGO ruchu dłużej niż to = martwy TCP (zabita aplikacja,
|
||||
// utracony mapping NAT). Klient pinguje co 2 s - 15 s to 7+ przegapionych
|
||||
// pingów, więc fałszywe pozytywy przy chwilowych zaniżeniach sieci są
|
||||
// praktycznie niemożliwe, a ghost nie zaśmieca rosteru dłużej niż trzeba.
|
||||
public static readonly TimeSpan SessionIdleTimeout = TimeSpan.FromSeconds(15);
|
||||
|
||||
public static ulong TotalBytesSent = 0;
|
||||
public static ulong TotalBytesReceived = 0;
|
||||
private static ulong CurrentBandwidthKps = 0;
|
||||
|
||||
// Zamiata sesje bez odebranego ruchu dłużej niż SessionIdleTimeout. Bez
|
||||
// tego zabita aplikacja (half-open TCP, brak Close frame) zostawała w
|
||||
// rosterze pokoju na zawsze: /room/users zwracało ghostów -> ghost kafelki
|
||||
// i "trwa rozmowa" u innych uczestników. TryRemove(KeyValuePair) jest
|
||||
// warunkowe po wartości - nie da się przypadkiem usunąć NOWEJ sesji, która
|
||||
// w międzyczasie nadpisała wpis tego samego userId (reconnect).
|
||||
private static void SweepStaleSessions()
|
||||
{
|
||||
DateTime cutoff = DateTime.UtcNow - SessionIdleTimeout;
|
||||
foreach (var room in Rooms)
|
||||
{
|
||||
foreach (var kvp in room.Value)
|
||||
{
|
||||
if (kvp.Value.LastSeenUtc >= cutoff) continue;
|
||||
if (!room.Value.TryRemove(new KeyValuePair<ulong, Session>(kvp.Key, kvp.Value))) continue;
|
||||
|
||||
//Zamknięcie kolejki kończy task-pump; Abort wywala zawieszone
|
||||
//ReceiveAsync/SendAsync martwego socketu -> receive-loop wejdzie
|
||||
//we swój finally i posprząta bufor (guard session==currentSession
|
||||
//zapobiega podwójnemu sprzątaniu)
|
||||
kvp.Value.SendQueue.Writer.TryComplete();
|
||||
try { kvp.Value.Socket.Abort(); } catch { }
|
||||
Console.WriteLine($"Voice: swept idle session room={room.Key} user={kvp.Key}");
|
||||
}
|
||||
|
||||
if (room.Value.IsEmpty) Rooms.TryRemove(room.Key, out _);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
|
|
@ -39,6 +74,8 @@ public class Program
|
|||
{
|
||||
if (entry.Value.resetAt <= nowSec) UsersListLimits.TryRemove(entry.Key, out _);
|
||||
}
|
||||
|
||||
SweepStaleSessions();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue