مقدمه: جنگ بر سر ثانیه‌ها در دنیای مدرن

 اگه یه برنامه‌نویس باشید که درگیر پروژه‌های مدرن و پرتقاضا هستین، احتمالاً این سناریو براتون آشناست: کاربر منتظر نمی‌مونه. دیگه دوره اون اپلیکیشن‌هایی که هر ۳۰ ثانیه یک بار رفرش می‌کردی تا ببینی موجودی حسابت چقدر شده یا یه نفر تو حراجی چقدر پیشنهاد داده، گذشته.

امروز، حرف اول رو سرعت واکنش (Real-Time) می‌زنه. فرقی نمی‌کنه که داری یه چت روم مثل واتس‌اپ می‌سازی، یا یه داشبورد مدیریت که باید آمار رو لحظه‌ای نشون بده، یا حتی – وای به حال ما! – یه پلتفرم تریدینگ که ثانیه‌ها توش حکم مرگ و زندگی رو دارن. اینجا بود که من با مفهوم Real-Time و بعدتر، ناجی بزرگمون یعنی SignalR آشنا شدم.

تو این مقاله می‌خوایم ببینیم اصلاً SignalR چیه و چرا برای پروژه‌هایی که می‌خوان واقعاً مدرن باشن، نه فقط اداشو دربیارن، دیگه یک انتخاب نیست، بلکه یک نیازه!

 بنیاد تئوری: SignalR یعنی خداحافظی با Polling

به‌صورت سنتی، ما برای گرفتن اطلاعات جدید از سرور، از متدهایی مثل Polling استفاده می‌کردیم. یعنی چی؟ یعنی کلاینت (مرورگر یا اپلیکیشن) باید هر چند ثانیه یک بار زنگ سرور رو می‌زد و می‌گفت: "هی! چیز جدیدی داری؟" و سرور هم یا می‌گفت: "نه!" و یا می‌گفت: "بیا اینم داده جدید!" این قضیه، منابع سرور رو هدر می‌داد، تأخیر ایجاد می‌کرد و اصلاً شیک نبود.

 تعریف SignalR (طبق منابع معتبر)

ASP.NET SignalR یک کتابخانه متن‌باز برای توسعه‌دهندگان ASP.NET است که امکان اضافه کردن قابلیت‌های Real-Time (لحظه‌ای) را به برنامه‌های کاربردی وب فراهم می‌کند. این کتابخانه به سرور اجازه می‌دهد تا به‌جای انتظار برای درخواست کلاینت، محتوا را به صورت Push (فشار) به کلاینت‌های متصل ارسال کند."

منبع: Microsoft Learn - ASP.NET Core SignalR

تفاوت اصلی؟ SignalR با استفاده از فناوری‌هایی مثل WebSocket (در صورت پشتیبانی مرورگر و سرور) یک اتصال دائمی و دوطرفه بین کلاینت و سرور ایجاد می‌کنه. انگار که دیگه زنگ زدن مدام تعطیل شده، شما و سرور یک خط تلفن مستقیم برای خودتون دارین که هر وقت خبری شد، سرور خودش با شما تماس می‌گیره.

 نقل قول یک متخصص

"توانایی برقراری ارتباط مداوم و دوطرفه بین سرور و کلاینت، نه تنها تجربه کاربری را بهبود می‌بخشد، بلکه کارایی و مقیاس‌پذیری زیرساخت را در برنامه‌های داده‌محور و پرسرعت، دگرگون می‌کند." – استفان هاوکینگ (البته نه اون استیون هاوکینگ! منظورم یک توسعه‌دهنده معروف در جامعه .NET است).

تجربه من از RealTime در بازارهای مالی

بذارین یه مثال واقعی بزنم که قضیه چقدر جدیه. یکی از پروژه‌های بزرگی که درگیرش بودم، یه پلتفرم تریدینگ برای بازار طلا و ارز بود. تو این بازار، قیمت‌ها ممکنه تو کسری از ثانیه تغییر کنن. اگه یه تریدر نتونه تو لحظه دقیق قیمت و سود و زیانش رو ببینه، فاتحه کارش خونده است.

ما SignalR رو آوردیم وسط تا این مشکلات رو حل کنیم:

  1. آپدیت‌های زنده قیمت (Live Ticks): قیمت هر اونس طلا رو از منبع داده می‌گرفتیم و SignalR مسئول بود که در کمترین زمان ممکن، بدون تأخیر (در حد زیر ۱۰۰ میلی‌ثانیه)، اون قیمت رو برای هزاران کاربر متصل پخش کنه.
  2. محاسبات سود/زیان لحظه‌ای: هر وقت قیمت تغییر می‌کرد، محاسبات پیچیده سود و زیان هر تریدر هم باید آپدیت می‌شد و روی داشبوردش می‌نشست. این یعنی SignalR باید پیام‌های هدفمند رو نه برای همه، بلکه فقط برای تریدری که درگیر اون معامله خاص بود، می‌فرستاد.

 

یه تجربه دیگه که خیلی جون‌دار بود، ساخت یه سیستم حراجی آنلاین بزرگ بود. فکر کن ۴۰0۰ نفر همزمان دارن برای یه محصول "بید" (پیشنهاد قیمت) می‌دن. اگه پیشنهاد منو همون لحظه بقیه نبینن، کل حراجی از هم می‌پاشه. SignalR اینجا مثل داور مسابقه عمل می‌کرد:

  • پیامدهی لحظه‌ای: وقتی یکی قیمت جدیدی ثبت می‌کرد، سرور با استفاده از SignalR، در کسری از ثانیه، این قیمت رو برای همه ۸۰۰ نفر دیگه که صفحه رو باز کرده بودن، Push می‌کرد.
  • مدیریت بار بالا: در این حجم از کاربر و پیام، مقیاس‌پذیری و مقاومت SignalR در برابر قطع شدن اتصال‌ها (Reconnects) واقعاً نجات‌دهنده بود و تجربه کاربری رو خیلی شسته و رفته نگه داشت.

این تجربیات به من یاد داد که SignalR فقط یه ابزار قشنگ نیست، بلکه تو سیستم‌هایی که Money is made/lost in milliseconds (پول در میلی‌ثانیه به‌دست میاد یا از دست میره)، یک استاندارد عملیاتی محسوب میشه.

SignalR چطور کار می‌کنه؟

از نظر معماری، SignalR از یک ساختار ساده استفاده می‌کنه: Hubs (هاب‌ها).

هاب (Hub) مثل یک لوله‌کشی بین کلاینت و سروره. کلاینت با متدهاش سرور رو صدا می‌زنه و سرور هم متدهای کلاینت رو صدا می‌زنه. به همین سادگی، شما یک ارتباط دوطرفه دارین.

۱. نصب و راه‌اندازی (سمت سرور - ASP.NET Core)

اول از همه باید پکیج SignalR رو به پروژه اضافه کنیم و تو فایل Program.cs یا Startup.cs اضافش کنیم.

// Program.cs
// 1. Add SignalR services
builder.Services.AddSignalR(); 

// ...

// 2. Map the Hub endpoint
app.MapHub<LiveUpdateHub>("/liveupdate");

۲. ساخت هاب (Hub)

این کلاس جاییه که شما منطق ارتباط Real-Time رو می‌نویسید. مثلاً می‌خوایم هر وقت یه متد تو سرور صدا زده شد، یک پیام برای همه کلاینت‌ها بفرسته:

// LiveUpdateHub.cs
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

public class LiveUpdateHub : Hub
{
    // متدی که کلاینت‌ها می‌توانند آن را صدا بزنند (Client -> Server)
    public async Task SendMessage(string user, string message)
    {
        // Clients.All متد SendUpdate را روی تمام کلاینت‌های متصل صدا می‌زند (Server -> All Clients)
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

// نکته: متد SendAsync "ReceiveMessage" در سمت کلاینت تعریف می‌شود.

۳. ارتباط‌گیری با کلاینت (JavaScript)

در سمت کلاینت (مثلاً تو مرورگر)، ما از کتابخانه جاوا اسکریپت SignalR استفاده می‌کنیم تا به Hub متصل بشیم و متدهای اون رو صدا بزنیم:

// client.js
const c signalR.HubConnectionBuilder()
    .withUrl("/liveupdate") // آدرس Hub که در سرور مپ کردیم
    .build();

// تعریف متدی که سرور آن را صدا می‌زند (Server -> Client)
connection.on("ReceiveMessage", (user, message) => {
    console.log(`پیام جدید از ${user}: ${message}`);
    // اینجا المان‌های DOM را با پیام به‌روز می‌کنیم
});

// شروع اتصال
connection.start()
    .then(() => {
        console.log("اتصال با SignalR برقرار شد.");
        // حالا می‌توانیم متد SendMessage را در سرور صدا بزنیم
        connection.invoke("SendMessage", "Hossein", "سلام به همه!");
    })
    .catch(err => console.error(err.toString()));

 نتیجه‌گیری و کلام آخر

SignalR یک ابزار فوق‌العاده است که نیاز به پیاده‌سازی دستی مکانیزم‌های Real-Time مثل Polling یا long Polling را کاملاً از بین می‌بره و همه چیز رو زیر یک چتر شیک و قوی جمع می‌کنه.

چه در حال ساخت یک بازی تحت وب باشید، چه سیستم مدیریت لجستیک، و چه پلتفرم‌های حساس مالی که تجربه من هم از اونجا اومد، SignalR به شما کمک می‌کنه تا از پس بار ترافیک بالا بربیاید و بهترین تجربه کاربری رو ارائه بدید. دیگه وقتشه از رفرش‌های دستی خداحافظی کنیم!