ایجاد برنامه چت با استفاده از SignalR

سه شنبه 14 دی 1395

در این مقاله، چگونگی ایجاد یک برنامه چت خصوصی را با استفاده از SignalR خواهیم آموخت . و در ادامه با ارائه یک مثال و بررسی مرحله به مرحله آن ، SignalR را بطور کامل برای شما شرح خواهیم داد .

ایجاد برنامه چت با استفاده از SignalR

معرفی :

در این مقاله قصد بررسی برنامه ای چت با استفاده از SignalR را داریم . قبل از شروع به کار نیاز داریم که با SignalR آشنا شویم . SignalR یک کتابخانه رایگان و Open است که برای توابع RealTime در Web Application ها مورد استفاده قرار میگیرد . Real-Time بدین معناست که سرور شما در سریع ترین زمان ممکن پاسخ درخواست کاربر را بدهد . 

حال ، به عنوان مثال ، ما در هنگام آپلود عکس قصد داریم که میزان درصدی از عکس که در سرور آپلود شده است را به کاربر نمایش دهیم . اینجاست که SignalR میتواند به کمک ما بیاید . کاربرد SignalR فقط در برنامه های چت نمیباشد . 

Theory :

تصویر زیر را مشاهده فرمایید :






امروزه ، هر برنامه ای نیاز به یک پاسخ Real-Time در قبال درخواست های ارسالی به سرور دارد . 
(Remote Procedure Calls (RPC  یکی از ظرفیت هایی ست که در SignalR جای دارد .  SignalR یک API را فراهم می آورد که به ما در ایجاد یک RPC ما بین سرور و کاربر کمک میکند . در واقع ، SignalR API به ما در مدیریت و اتصال آنها در زمان نیاز کمک خواهد کرد . به زبان ساده تر ، SignalR اتصال بین سرور و کاربر را فراهم می آورد ، این امکان را میدهد که سرور توابع سمت کاربر را فراخوانی کند و از سمت کاربر ، سرور را فراخوانی کند . 

این امر Server-Push نامیده میشود . SignalR با HTTP  شروع میکند و سپس در صورت در درسترس بودن اتصال به یک WebSocket می رود . WebSocket یک پروتکل است که یک کانال ارتباطی تمام دوطرفه را از طریق یک اتصال Single TCP برقرار میکند . یک از مزیت های استفاده از WebSocket این است که هم از طریق سمت سرور در دسترس است و هم از سمت کاربر برنامه در دسترس میباشد . این یکی از دلایلی است که SignalR را کارآمد میکند . SignalR تراکنش را بر مبنای Browser قرار میدهد . این بدین معناست که اگر مرورگرها  نوع تراکنش مورد درخواست SignalR را پشتیبانی کنند. در مرحله بعد انواع تراکنش ها را بررسی خواهیم کرد :

HTML 5 Transports :

• WebSockets همانطور که مورد بحث قرار دادیم . این تراکنش سعی بر این دارد که بدون وقفه باشد و یک اتصال دو طرفه بین سرور و کاربر در صورتی که مرورگر پشتیبانی کند ، برقرار کند . 

• Server Sent Event ، همچنین با نام Event Source شناخته میشود، که وسط تمامی مرورگرها به غیر از IE پشتیانی میشود . 

Comet Transports :

Comet معمولا ، یک مدل web application است که یک درخواست long-held HTTP این امکان را به سرور میدهد که داده ای  به یک کاربر ارسال کند . 

• Forever Frame : این فقط توسط Internet Explorer پشتیبانی میشود . یک فریم پنهانی ایجاد کرده ، یک درخواست به نقطه پایانی سرور میسازد . سرور یک اتصال یک طرفه ایجاد میکند و به ازای هر درخواست یک اتصال جدی ایجاد میکند .

• Ajax Polling این در واقع همان Long Polling است ، که بدون وقفه است . این درخواست ها را Polls میکند و تا رسیدن جواب از سمت سرور صبر میکند . 


Practical -- تمرین :

ما با استفاده از SignalR یک برنامه چت خواهیم نوشت . SignalR را نصب خواهیم کرد ، به ازای هر کاربر یک Hub ایجاد خواهیم کرد . یک پروژه جدید MVC در VS ایجاد کرده و با استفاده از دستور زیر در Manage NuGet Console ;jhfohki کتابخانه SignalR را به پروژه اضافه کنید . 

PM > Install-Package Microsoft.AspNet.SignalR

تمام وابستگی های SignalR در زمان اجرای این دستور به پروژه اضافه خواهد شد . 



بعد از اتمام نصب ، کتابخانه هایی که در تصویر بالا مشاهده میکنید به پروژه شما اضافه خواهد شد . ما  یک کلاس با نام Startup.cs داریم که در Root پروژه قرار خواهد گرفت . کدهای این کلاس بصورت زیر است :

using Owin;  
using Microsoft.Owin;  
[assembly: OwinStartup(typeof(SignalRChat.Startup))]  
namespace SignalRChat   
{  
    public class Startup   
    {  
        public void Configuration(IAppBuilder app) { // Any connection or hub wire up and configuration should go here app.MapSignalR();   
        }   
    }  
 }


این یک برنامه بر مبنای OWIN است . هر برنامه OWIN یک کلاس Startup.cs دارد ، که مولفه های لازمه ی برنامه به آن اضافه میشود . همانطور که در تصویر زیر مشاهده میفرمایید ، در این پروژه دو فایل Scripts دیگر با نصب پکیج SignalR به پروژه اضافه خواهد شد . 



این Scripts ها برای فعال سازی SignalR در View Page مورد استفاده قرار خواهد گرفت . ما نیاز به اضافه کردن یک کلاس Hub به فولدر Hubs داریم ، نام این کلاس را LetsChatHub.cs  میگذاریم . که همانند زیر است . 

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using Microsoft.AspNet.SignalR;  
namespace LetsChatApplication.Hubs  
{  
    public class LetsChatHub: Hub  
    {  
        public void Send(string name, string message, string connId)  
        {  
            Clients.Client(connId).appendNewMessage(name, message);  
        }  
    }  
} 


متد بالا سه پارامتر name , messaage و connId را می پذیرد . connId به ما کمک میکند که پیام خود را به یک شخص خاصی ارسال کنیم . اگر شما میخواهید پیام ها بصورت عمومی ارسال و دریافت شود میتوانید این پارامتر را حذف کنید و که در این صورت متد ما بصورت زیر خواهد شد :

namespace LetsChatApplication.Hubs  
{  
    public class LetsChatHub: Hub  
    {  
        public void Send(string name, string message)  
        {  
            Clients.All.appendNewMessage(name, message);  
        }  
    }  
} 

متد Send با پارامترهایش ، توسط کاربر  بعد از تنظیم اتصال سمت کاربر و زمانی که سرور درخواست را دریافت کرد ، درخواست داده میشود ، پردازشی انجام میشود و پاسخ به کاربر با استفاده از appendNewMessage دوباره ارسال میشود . شما نیاز به اضافه کردن یک Controller دارید . نام آن و Action Method آن را LetsChat میگذاریم . View این Controller همانند زیر است . 

@{  
    ViewBag.Title = "LetsChat";  
  
}  
  
  
<h2>Lets Chat</h2>  
<link href="~/Content/sweetalert.css" rel="stylesheet" />  
  
<div class="form-group col-xl-12">  
    <label class="control-label">Your connection Id</label><br />  
    <input type="text" class="col-lg-12 text-primary" id="frndConnId" placeholder="Paste your friend's connection Id" /><br /><br />  
    <label class="control-label">Your Message</label><br />  
    <textarea type="text" class="col-lg-10 text-primary" id="message"></textarea>      
  
    <input type="button" class="btn btn-primary" id="sendmessage" value="Send" /><br /><br />  
    <img src="~/Content/smile.jpg" width="20" height="20" id="smile" style="cursor:pointer"/>  
    <img src="~/Content/uff.jpg" width="20" height="20" id="ufff" style="cursor:pointer" />  
    <div class="container chatArea">  
        <input type="hidden" id="displayname" />  
        <ul id="discussion"></ul>  
    </div>  
</div>  
<br />  
<input type="hidden" id="connId" />  
  
<!--Reference the autogenerated SignalR hub script. -->  
@section scripts {  
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>  
    <script src="~/Content/sweetalert.min.js"></script>  
    <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>  
    <script src="~/signalr/hubs"></script>  
    <script>  
        //var userName = "";  
        //var sessionVal = '';  
        $(function () {  
            // Reference the auto-generated proxy for the hub.  
            var chat = $.connection.letsChatHub;  
              
            debugger;  
  
            // Create a function that the hub can call back to display messages.  
            chat.client.addNewMessageToPage = function (name, message) {  
                // Add the message to the page.  
                $('#discussion').append('<li><strong>' + htmlEncode(name)  
                    + '</strong>: ' + htmlEncode(message) + '</li>');  
            };  
            // Get the user name and store it to prepend to messages.  
            swal({  
                title: "Lets Chat!",  
                text: "<span style='color:#f8bb86;font-weight:700;'>Enter your name:</span>",  
                type: "input",  
                html: true,  
                showCancelButton: true,  
                closeOnConfirm: true,  
                animation: "slide-from-top",  
                inputPlaceholder: "Your Name"  
            },  
            function (inputValue) {  
                userName = inputValue;  
                if (inputValue === false) return false;  
                if (inputValue === "") {  
                    swal.showInputError("You need to type your name!");  
                    return false;  
                }  
                $('#displayname').val(inputValue);  
            });  
            // Set initial focus to message input box.  
            $('#message').focus();  
            $('#message').keypress(function (e) {  
                if (e.which == 13) {//Enter key pressed  
                    $('#sendmessage').trigger('click');//Trigger search button click event  
                }  
            });  
            $("#smile").click(function () {  
  
            });  
            // Start the connection.  
            $.connection.hub.start().done(function () {  
  
                $('#sendmessage').click(function () {  
                    // Call the Send method on the hub.  
                    var connId = $("#connId").val();  
                    var frndConnId = $("#frndConnId").val();  
                    var finalConnId = frndConnId == "" ? $.connection.hub.id : frndConnId;  
                    chat.server.send($('#displayname').val(), $('#message').val(), finalConnId);  
                    $("#connId").val($.connection.hub.id);  
                    if (frndConnId == "") {  
                        swal("You connection Id", $.connection.hub.id, "success");  
                    }  
                    // Clear text box and reset focus for next comment.  
                    $('#discussion').append('<li><strong>' + htmlEncode($('#displayname').val())  
                   + '</strong>: ' + htmlEncode($('#message').val()) + '</li>');  
                    $('#message').val('').focus();  
                });  
            });  
     
        });  
    // This optional function html-encodes messages for display in the page.  
    function htmlEncode(value) {  
        var encodedValue = $('<div />').text(value).html();  
        return encodedValue;  
    }  
    </script>  
}  

ما یک UI معمولی داریم که کاربر بتواند پیامی بنویسد و با استفاده از دکمه ارسال متدهای سرور را فراخوانی کند . کد بالا را برای درک بهتر ، قسمت به قسمت بررسی خواهیم کرد . 

var chat = $.connection.letsChatHub; 

در کد بالا ، ما یک اتصال را برای Hub Class تنظیم کردیم . اگر توجه کنید letsChatHub ، با نام فایل hub class ای که به پروژه اضافه کردیم ،  یکی است . با استفاده از این ، ما از chat برای پردازش متد های send استفاده میکنیم . 

$.connection.hub.start().done(function()  
            {  
            $('#sendmessage').click(function()  
                         {  
                        // Calls the Send method on the hub. chat.server.send($('#displayname').val(), $('#message').val(), finalConnId); 

chat.server.send خود تفسیری می باشد . این اتصال چت را برای فراخوانی server send method تنظیم میکند . 

chat.client.appendNewMessage = function (name, message) {  
//  
} 

این زمانی که سرور درخواست را دریافت کرد و متد را در سمت سرور فراخوانی کرد ، فراخوانی می شود . 


چگونگی کارکرد برنامه :

کدهای این برنامه را میتوانید در انتهای مقاله دانلود کنید . 

• در ابتدای برنامه یک Alert نمایش داده میشود که از کاربر میخواهد که نام خود را وارد کند . 



زمانی که شما نام خود را وارد میکنید ، شما یک TextBox خواهید دید که از شما شناسه اتصال دوستی که قصد چت کردن با آن را دارید را میخواهد ، بعد از آن کافیست یک پیام ارسال کنید ، یک popUp جدید باز خواهد شد که شناسه اتصال شما را خواهد داد . این Id را در اختیار دوست خود قرار دهید . به یاد داشته باشید که تنها کسی که شناسه اتصال شما را دارد توانایی ارسال پیام به شما را دارد . 





تصویر زیر فضای برنامه ما رانمایش میدهد :



نتیجه گیری :

این فقط یک برنامه چت ساده است . که این امکان را به شما میدهد که با دوست خود به چت کردن بپردازید . اما SignalR فقط محدود به این امر نمیشود . کاربرد های بسیار دیگری وجود دارد که ما در مقاله های بعدی به بررسی انها خواهیم پرداخت . 

آموزش asp.net mvc

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید