Initial version
This commit is contained in:
259
Demo/Program.cs
Normal file
259
Demo/Program.cs
Normal file
@@ -0,0 +1,259 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
||||
|
||||
namespace EonaCat.QuicNet
|
||||
{
|
||||
/// <summary>
|
||||
/// EonaCat.QuicNet — Demo
|
||||
/// Starts a server and two clients to demonstrate various features of the library, including sending messages, groups, nicknames, and graceful disconnects.
|
||||
/// </summary>
|
||||
internal static class Demo
|
||||
{
|
||||
private static void Main()
|
||||
{
|
||||
Console.WriteLine("EonaCat QuicNet — Features demo ");
|
||||
|
||||
// 1. Server setup
|
||||
|
||||
var serverOptions = new QuicServerOptions
|
||||
{
|
||||
Port = 9876,
|
||||
MaxConnections = 100_000,
|
||||
HeartbeatIntervalInMilliseconds = 5_000,
|
||||
ClientTimeoutInMilliseconds = 15_000,
|
||||
EnableHeartbeat = true,
|
||||
NoDelay = true
|
||||
};
|
||||
|
||||
var server = new QuicServer(serverOptions);
|
||||
|
||||
server.Started += (s, e) => Log("SERVER", $"Listening on port {e.Port}");
|
||||
server.Stopped += (s, e) => Log("SERVER", "Stopped");
|
||||
server.ClientConnected += (s, e) => Log("SERVER", string.Format("+ Connected [{0}...]", e.Client.SessionId.Substring(0, 8)));
|
||||
server.ClientDisconnected += (s, e) => Log("SERVER", string.Format("- Disconnected [{0}...] Reason={1}", e.Client.SessionId.Substring(0, 8), e.Reason));
|
||||
|
||||
server.DataReceived += (s, e) =>
|
||||
{
|
||||
var id = e.Client.Nickname ??
|
||||
(e.Client.SessionId.Length > 8
|
||||
? e.Client.SessionId.Substring(0, 8)
|
||||
: e.Client.SessionId);
|
||||
|
||||
Log("SERVER", $" Data from [{id}]: {e.Text}");
|
||||
};
|
||||
|
||||
server.ClientJoinedGroup += (s, e) => Log("SERVER", $" [{e.Client.Nickname ?? "?"}] joined group '{e.GroupName}'");
|
||||
server.ClientLeftGroup += (s, e) => Log("SERVER", $" [{e.Client.Nickname ?? "?"}] left group '{e.GroupName}'");
|
||||
server.Error += (s, e) => Log("SERVER", $" ERROR: {e.Exception.Message} [{e.Context}]");
|
||||
|
||||
server.Start();
|
||||
Thread.Sleep(200);
|
||||
|
||||
// 2. Client A
|
||||
|
||||
var clientA = new QuicClient(new QuicClientOptions
|
||||
{
|
||||
Host = "127.0.0.1",
|
||||
Port = 9876,
|
||||
Nickname = "Alice",
|
||||
AutoReconnect = true,
|
||||
ReconnectMaxAttempts = 5,
|
||||
ReconnectBaseDelayMs = 500
|
||||
});
|
||||
|
||||
clientA.Connected += (s, e) => Log("CLIENT-A", string.Format("Connected session={0}...", e.SessionId.Substring(0, 8)));
|
||||
clientA.Disconnected += (s, e) => Log("CLIENT-A", $"Disconnected reason={e.Reason}");
|
||||
clientA.DataReceived += (s, e) => Log("CLIENT-A", $" ← {e.Text}");
|
||||
clientA.Reconnecting += (s, e) => Log("CLIENT-A", $" Reconnecting attempt {e.Attempt}/{e.MaxAttempts}...");
|
||||
clientA.ReconnectFailed += (s, e) => Log("CLIENT-A", " Reconnect gave up.");
|
||||
clientA.Error += (s, e) => Log("CLIENT-A", $" ERROR: {e.Exception.Message}");
|
||||
|
||||
clientA.Connect();
|
||||
Thread.Sleep(300);
|
||||
|
||||
// 3. Client B
|
||||
|
||||
var clientB = new QuicClient("127.0.0.1", 9876, "Bob");
|
||||
clientB.Connected += (s, e) => Log("CLIENT-B", string.Format("Connected session={0}...", e.SessionId.Substring(0, 8)));
|
||||
clientB.Disconnected += (s, e) => Log("CLIENT-B", $"Disconnected reason={e.Reason}");
|
||||
clientB.DataReceived += (s, e) => Log("CLIENT-B", $" ← {e.Text}");
|
||||
clientB.Error += (s, e) => Log("CLIENT-B", $" ERROR: {e.Exception.Message}");
|
||||
clientB.Connect();
|
||||
Thread.Sleep(300);
|
||||
|
||||
Console.WriteLine();
|
||||
Log("DEMO", "Basic sends");
|
||||
|
||||
// 4. Send string from client
|
||||
|
||||
clientA.Send("Hello from Alice!");
|
||||
clientB.Send("Hello from Bob!");
|
||||
Thread.Sleep(100);
|
||||
|
||||
// 5. Send bytes
|
||||
|
||||
clientA.Send(new byte[] { 0xDE, 0xAD, 0xBE, 0xEF }); // raw bytes
|
||||
Thread.Sleep(100);
|
||||
|
||||
// 6. Broadcast from server
|
||||
|
||||
Console.WriteLine();
|
||||
Log("DEMO", "Broadcast");
|
||||
int n = server.Broadcast("Server broadcast to everyone!");
|
||||
Log("SERVER", $" Sent to {n} clients");
|
||||
Thread.Sleep(100);
|
||||
|
||||
// 7. Send to single client
|
||||
|
||||
Console.WriteLine();
|
||||
Log("DEMO", "SendTo (single)");
|
||||
|
||||
var clients = new System.Collections.Generic.List<IQuicClient>(server.GetClients());
|
||||
if (clients.Count >= 2)
|
||||
{
|
||||
var aliceSession = FindByNickname(server, "Alice");
|
||||
var bobSession = FindByNickname(server, "Bob");
|
||||
|
||||
if (aliceSession != null)
|
||||
{
|
||||
server.SendTo(aliceSession.SessionId, "Private message to Alice only");
|
||||
}
|
||||
|
||||
if (bobSession != null)
|
||||
{
|
||||
server.SendTo(bobSession.SessionId, "Private message to Bob only");
|
||||
}
|
||||
}
|
||||
Thread.Sleep(100);
|
||||
|
||||
// 8. Groups
|
||||
|
||||
Console.WriteLine();
|
||||
Log("DEMO", "Groups");
|
||||
|
||||
var alice = FindByNickname(server, "Alice");
|
||||
var bob = FindByNickname(server, "Bob");
|
||||
|
||||
if (alice != null)
|
||||
{
|
||||
server.AddToGroup(alice.SessionId, "vip");
|
||||
}
|
||||
|
||||
if (bob != null)
|
||||
{
|
||||
server.AddToGroup(bob.SessionId, "vip");
|
||||
}
|
||||
|
||||
if (alice != null)
|
||||
{
|
||||
server.AddToGroup(alice.SessionId, "team-a");
|
||||
}
|
||||
|
||||
Thread.Sleep(100);
|
||||
|
||||
int vipCount = server.SendToGroup("vip", "VIP broadcast (Alice + Bob)");
|
||||
Log("SERVER", $" Sent to {vipCount} VIP clients");
|
||||
|
||||
int teamACount = server.SendToGroup("team-a", "Team-A message (Alice only)");
|
||||
Log("SERVER", $" Sent to {teamACount} team-a clients");
|
||||
|
||||
Thread.Sleep(100);
|
||||
|
||||
// 9. Nickname change
|
||||
|
||||
Console.WriteLine();
|
||||
Log("DEMO", "Nickname change");
|
||||
clientA.Nickname = "Alice_Renamed";
|
||||
Thread.Sleep(100);
|
||||
Log("CLIENT-A", $"Nickname is now: {clientA.Nickname}");
|
||||
|
||||
// 10. Encoding variants
|
||||
|
||||
Console.WriteLine();
|
||||
Log("DEMO", "Unicode / Encoding");
|
||||
clientB.Send("あなたを決してあきらめない", Encoding.UTF8);
|
||||
Thread.Sleep(100);
|
||||
|
||||
// 11. Server queries
|
||||
|
||||
Console.WriteLine();
|
||||
Log("DEMO", "Server queries");
|
||||
Log("SERVER", $" Connected clients: {server.ClientCount}");
|
||||
foreach (var g in server.GetGroups())
|
||||
{
|
||||
int cnt = 0;
|
||||
foreach (var _ in server.GetGroupClients(g))
|
||||
{
|
||||
cnt++;
|
||||
}
|
||||
|
||||
Log("SERVER", $" Group '{g}': {cnt} member(s)");
|
||||
}
|
||||
|
||||
// 12. Remove from group
|
||||
|
||||
if (alice != null)
|
||||
{
|
||||
server.RemoveFromGroup(alice.SessionId, "vip");
|
||||
Log("SERVER", " Alice removed from 'vip'");
|
||||
}
|
||||
Thread.Sleep(100);
|
||||
|
||||
// 13. Extension methods
|
||||
|
||||
Console.WriteLine();
|
||||
Log("DEMO", "Extensions");
|
||||
server.BroadcastText("Extension broadcast text!");
|
||||
server.SendToGroupText("team-a", "Extension group-text to team-a");
|
||||
Thread.Sleep(100);
|
||||
|
||||
// 14. Graceful disconnect
|
||||
|
||||
Console.WriteLine();
|
||||
Log("DEMO", "Graceful disconnect");
|
||||
clientB.Disconnect("Bob says goodbye");
|
||||
Thread.Sleep(300);
|
||||
|
||||
// 15. Server kick
|
||||
|
||||
if (alice != null)
|
||||
{
|
||||
server.Kick(alice.SessionId, "Demo kick");
|
||||
Thread.Sleep(300);
|
||||
}
|
||||
|
||||
// 16. Shutdown
|
||||
|
||||
Console.WriteLine();
|
||||
Log("DEMO", "Server shutdown");
|
||||
server.Stop();
|
||||
Thread.Sleep(200);
|
||||
|
||||
clientA.Dispose();
|
||||
clientB.Dispose();
|
||||
server.Dispose();
|
||||
|
||||
Console.WriteLine("Demo complete!");
|
||||
}
|
||||
|
||||
|
||||
private static void Log(string source, string message) => Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] [{source,-10}] {message}");
|
||||
|
||||
private static IQuicClient FindByNickname(QuicServer server, string nickname)
|
||||
{
|
||||
foreach (var client in server.GetClients())
|
||||
{
|
||||
if (string.Equals(client.Nickname, nickname, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user