Grup, Pengguna & Pengelolaan Koneksi
Kelola grup, arahkan pesan ke pengguna atau koneksi tertentu, dan tangani peristiwa siklus hidup saat terhubung atau terputus.
Grup, Pengguna & Pengelolaan Koneksi adalah pelajaran C# Academy gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar C# Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus C# Academy mencakup 4 pelajaran total.
Mengapa Grup dan Pengguna?
Dalam aplikasi nyata, Anda jarang ingin menyiarkan pesan ke ALL klien. Grup SignalR memungkinkan Anda menargetkan sebagian koneksi (misalnya, ruang obrolan), sedangkan pengguna memungkinkan Anda mengalamatkan semua koneksi milik pengguna terautentikasi tertentu.
Menambahkan Koneksi ke Grup
Panggil Groups.AddToGroupAsync() dengan ID koneksi dan nama grup. Satu koneksi dapat menjadi anggota beberapa grup secara bersamaan.
public class ChatHub : Hub
{
public async Task JoinRoom(string roomName)
{
await Groups.AddToGroupAsync(Context.ConnectionId, roomName);
await Clients.Group(roomName)
.SendAsync("UserJoined", Context.User!.Identity!.Name);
}
public async Task LeaveRoom(string roomName)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, roomName);
await Clients.Group(roomName)
.SendAsync("UserLeft", Context.User!.Identity!.Name);
}
}Mengirim ke Grup
Gunakan Clients.Group(name) untuk mengirim pesan ke semua koneksi dalam grup. Opsi penargetan lainnya mencakup GroupExcept dan Groups (beberapa grup sekaligus).
public async Task SendToRoom(string roomName, string message)
{
var sender = Context.User!.Identity!.Name;
// Everyone in the room
await Clients.Group(roomName)
.SendAsync("ReceiveMessage", sender, message);
// Everyone in the room except the sender
await Clients.GroupExcept(roomName, Context.ConnectionId)
.SendAsync("ReceiveMessage", sender, message);
}Penargetan Berbasis Pengguna
Ketika pengguna membuka beberapa tab peramban atau perangkat, pengguna tersebut memiliki beberapa koneksi. Clients.User(userId) mengirim pesan ke ALL koneksi pengguna tersebut secara bersamaan.
// Send to all connections of user with ID "user-123"
await Clients.User("user-123")
.SendAsync("Notification", "Your order has shipped!");
// SignalR uses the NameIdentifier claim by default.
// Context.UserIdentifier returns the current user's ID.
var myId = Context.UserIdentifier;
await Clients.User(myId!).SendAsync("Ack", "Server received your message");Penyedia ID Pengguna Kustom
Secara bawaan, SignalR menggunakan klaim NameIdentifier sebagai ID pengguna. Terapkan IUserIdProvider untuk menggunakan klaim lain atau logika kustom.
public class EmailUserIdProvider : IUserIdProvider
{
public string? GetUserId(HubConnectionContext connection)
{
return connection.User?.FindFirst(ClaimTypes.Email)?.Value;
}
}
// Register:
builder.Services.AddSingleton<IUserIdProvider, EmailUserIdProvider>();Melacak Status Koneksi
SignalR tidak mempertahankan status koneksi di antara pemutusan. Lacak pemetaan ID pengguna ke ID koneksi Anda sendiri dalam kamus yang aman bagi utas (server tunggal) atau Redis (banyak server).
public class ConnectionTracker
{
private readonly ConcurrentDictionary<string, HashSet<string>> _userConnections
= new();
public void AddConnection(string userId, string connectionId)
=> _userConnections.GetOrAdd(userId, _ => new()).Add(connectionId);
public void RemoveConnection(string userId, string connectionId)
{
if (_userConnections.TryGetValue(userId, out var conns))
{
conns.Remove(connectionId);
if (conns.Count == 0) _userConnections.TryRemove(userId, out _);
}
}
public IEnumerable<string> GetConnections(string userId)
=> _userConnections.TryGetValue(userId, out var c) ? c : Enumerable.Empty<string>();
}Mengelola Grup Otomatis di OnConnected/OnDisconnected
Pola yang umum adalah menambahkan pengguna terautentikasi secara otomatis ke grup pribadi mereka dalam OnConnectedAsync, sehingga Anda dapat menargetkan mereka berdasarkan nama grup tanpa pelacakan kustom.
public override async Task OnConnectedAsync()
{
// Add to a personal group named by user ID
var userId = Context.UserIdentifier;
if (userId is not null)
await Groups.AddToGroupAsync(Context.ConnectionId, userId);
await base.OnConnectedAsync();
}
// Now send to a user by their personal group:
await _hub.Clients.Group(userId)
.SendAsync("Update", payload);Mengirim dari Layanan Latar Belakang dengan Grup
Dengan menggunakan IHubContext, Anda dapat menargetkan grup dan pengguna dari layanan latar belakang — sempurna untuk notifikasi async yang dipicu oleh peristiwa dalam sistem Anda.
public class OrderShippedHandler : INotificationHandler<OrderShipped>
{
private readonly IHubContext<OrderHub> _hub;
public OrderShippedHandler(IHubContext<OrderHub> hub) => _hub = hub;
public async Task Handle(OrderShipped notification, CancellationToken ct)
{
// Push to the customer's personal group
await _hub.Clients.Group(notification.CustomerId.ToString())
.SendAsync("OrderShipped",
new { notification.OrderId, notification.TrackingNumber },
ct);
}
}Persistensi Keanggotaan Grup
Keanggotaan grup tidak disimpan secara persisten—jika server dimulai ulang atau bus pesan Redis kehilangan status, grup akan kosong. Bergabunglah kembali ke grup saat tersambung kembali menggunakan peristiwa onreconnected pada klien.
// JavaScript client: re-join groups after reconnect
connection.onreconnected(async connectionId => {
console.log(`Reconnected as ${connectionId}`);
// Re-join previously joined rooms
for (const room of joinedRooms) {
await connection.invoke("JoinRoom", room);
}
});Kehadiran: Deteksi Daring/Luring
Lacak status daring dengan menghitung koneksi per pengguna di OnConnected/OnDisconnected dan menyiarkan peristiwa kehadiran ke grup yang relevan.
public override async Task OnConnectedAsync()
{
var userId = Context.UserIdentifier!;
var count = _tracker.AddConnection(userId, Context.ConnectionId);
if (count == 1) // first connection for this user
await Clients.Others.SendAsync("UserOnline", userId);
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? ex)
{
var userId = Context.UserIdentifier!;
var count = _tracker.RemoveConnection(userId, Context.ConnectionId);
if (count == 0) // no more connections
await Clients.Others.SendAsync("UserOffline", userId);
await base.OnDisconnectedAsync(ex);
}Pemeriksaan Singkat
Saat pengguna membuka tiga tab peramban, apa yang dilakukan Clients.User(userId)?
Ringkasan: Grup, Pengguna, dan Pengelolaan Koneksi
Poin penting:
Groups.AddToGroupAsync/RemoveFromGroupAsync: mengelola keanggotaan grupClients.Group(name): mengirim ke sebagian koneksiClients.User(userId): mengirim ke semua koneksi pengguna- Implementasikan
IUserIdProvideruntuk klaim ID pengguna kustom - Grup tidak disimpan secara persisten—bergabunglah kembali saat tersambung kembali
- Lacak jumlah koneksi dalam ConcurrentDictionary untuk deteksi kehadiran
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Grup, Pengguna & Pengelolaan Koneksi” gratis?
Ya — teks lengkap “Grup, Pengguna & Pengelolaan Koneksi” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus C# Academy, upgrade ke CoddyKit PRO. Kursus C# Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Grup, Pengguna & Pengelolaan Koneksi”?
Kelola grup, arahkan pesan ke pengguna atau koneksi tertentu, dan tangani peristiwa siklus hidup saat terhubung atau terputus. Kamu berlatih C# Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai C# Academy?
Tidak diperlukan pengalaman sebelumnya. C# Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.
Berapa lama pelajaran “Grup, Pengguna & Pengelolaan Koneksi” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran C# Academy ini?
Ya. Setiap pelajaran C# Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Hub & Koneksi SignalR
- Grup, Pengguna & Pengelolaan Koneksi
- Hub Bertipe Kuat
- Penskalaan dengan Redis Backplane