1. 程式人生 > >SignalR入門學習記錄

SignalR入門學習記錄

SignalR有兩種客戶端和伺服器端的資料互動模式:長連線模式和Hub(集線器模式)

1、SignalR的長連線模式

伺服器端,新建一個繼承PersistentConnection的自定義類(如果是vs2013,則編輯器新建專案裡面會有建立“永久連結類”選項,這裡我是用的vs2012,需要自定義個類)這個類的作用就是處理伺服器接受客戶端傳送過來的訊息以及將訊息傳送到客戶端,如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;


using Microsoft.AspNet.SignalR;


namespace MvcApplication2.SignalR
{
    public class SignalRControll:PersistentConnection
    {
        protected override System.Threading.Tasks.Task OnConnected(IRequest request, string connectionId)
        {
            ///當客戶端連線到伺服器的時候
            return Connection.Send(connectionId, "歡迎");            
        }
        protected override System.Threading.Tasks.Task OnReceived(IRequest request, string connectionId, string data)
        {
            ///當伺服器接收到客戶端傳送過來的訊息的時候
            //return Connection.Broadcast(data);  //向所有線上客戶端傳送訊息 1
            return Connection.Send(connectionId, data);//向指定的客戶端傳送訊息 2


        }
        protected override System.Threading.Tasks.Task OnDisconnected(IRequest request, string connectionId, bool stopCalled)
        {
            ///當客戶端和伺服器斷開連線的時候
            return base.OnDisconnected(request, connectionId, stopCalled);
        }
        protected override System.Threading.Tasks.Task OnReconnected(IRequest request, string connectionId)
        {
            ///當客戶端和伺服器重新連線的時候
            return base.OnReconnected(request, connectionId);
        }
    }
}

完成了上面的訊息處理程式碼之後怎樣才能在系統中的後代跑起來上面的程式碼呢?用微軟提供的Owin,新建一個包含Configuration(IAppBuilder app)的方法的自定義的類(如果是vs2013,則選擇建立項的時候選擇“OWIN Startup類“選項即可)

using Microsoft.Owin;
using Owin;


[assembly: OwinStartup(typeof(MvcApplication2.SignalR.HostStart))]  //主要是在此處註冊自定義的類
namespace MvcApplication2.SignalR
{
    public class HostStart
    {
        public void Configuration(IAppBuilder app)  //
        {
            app.MapSignalR<SignalRControll>("/myconnection");  //註冊永久連結 1  客戶端初始化永久連結的時候的引數要和此處一致,即“/myconnection”這個引數
            app.MapSignalR();  //註冊集線器 2


        }
    }
}

注意紅色部分說明,如果只選用永久連線模式,則需要把下面的程式碼註釋掉,反之亦然

客戶端示例程式碼:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    
    <script src="Scripts/jquery-1.7.1.min.js"></script>
    <script src="Scripts/jquery.signalR-2.2.1.min.js"></script>


    <script>
        //獲取當前時間
        function getDate(){
            var date=new Date();
            return date.getFullYear()+"/"+date.getMonth()+"/"+date.getDate()+"  "+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
        }
        var conn = $.connection("/myconnection");  //初始化永久連線,注意此處的“/myconnection”引數需要和後臺註冊永久連結模式時的引數要保持一致
        $(function () {
            conn.start().done(function (data) {  //當客戶端連線上了伺服器的時候執行的程式碼
                $("#history").val(data.id);  
            });
            conn.received(function (data) {  //當客戶端收到伺服器傳過來的資訊的時候執行的程式碼
                var history = $("#history").val();
                history += "\n" + getDate() + "\n" + data;
                $("#history").val(history);
            });
        });
        function sendMSG() {
            var content = $("#content").val();
            if (content != "") {
                conn.send(content);  //向伺服器傳送訊息
            }
        }
    </script>
</head>
<body>
    <p>
        聊天記錄:<br />
        <textarea id="history"></textarea>        
    </p>
    <p>
        傳送內容:<br />
        <input type="text" id="content" /><br />
        <input type="button" value="傳送" onclick="sendMSG()" />
    </p>
</body>
</html>

執行結果截圖如下:


如果將上面綠色程式碼處的程式碼1註釋去掉的話,那麼當在多個瀏覽器裡面開啟這個頁面,然後再其中一個瀏覽器傳送一條訊息的時候,其他幾個瀏覽器的頁面也會顯示這條訊息

2、Hub(集線器模式)模式

後臺程式碼部分,新建一個繼承Hub類的自定義類,如下:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;


namespace MvcApplication2.SignalR
{
    public class MyHub:Hub
    {

       public void ServerHello()
        {
            ///自定義方法,客戶端可以“直接”訪問的方法
        }
        public void ServerHello(string data,int index)
        {
            ///自定義方法,客戶端可以“直接”訪問的方法
            Debug.WriteLine("客戶端呼叫伺服器端方法");
            Clients.All.clientHello(data,index);  //呼叫客戶端的方法clientHello,並且傳遞兩個引數獲取,注意客戶端必須要定義一個包含兩個引數,且名稱為clientHello的函式

          //上面Clients.All表示向所有線上客戶端傳送訊息
        }


        public void ServerSend(string content, string connectionid)
        {
            ///自定義方法客戶端可以“直接”訪問的方法
            Clients.Client(connectionid).getServerContent(content);  //呼叫客戶端的方法getServerContent,並且傳遞一個引數過去,注意客戶端必須要定義一個包含一個引數,且名稱為getServerContent的函式

          //Clients.Client(connectionid)表示向特定使用者傳送訊息 
        }


        public override System.Threading.Tasks.Task OnConnected()
        {    
            ///當客戶端連線到伺服器的時候
            return Clients.Client(Context.ConnectionId).getConnectionID(Context.ConnectionId);
        }


        public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
        {
            ///當客戶端和伺服器斷開連線的時候
            return base.OnDisconnected(stopCalled);
        }


        public override System.Threading.Tasks.Task OnReconnected()
        {
            ///當客戶端和伺服器重新連線的時候
            return base.OnReconnected();
        }
    }
}

集線器模式的程式碼和永久連結模式的程式碼很相似,也是可以重寫幾個基類的方法,當時集線器模式裡面沒有接受資訊的程式碼,而且可以自定義函式,這些自定義函式可以被客戶端“直接“訪問,同樣完成了上面的程式碼也需要在後臺註冊,這樣系統才能在後臺將上面的程式碼跑起來,註冊的方式已經在上面的程式碼裡寫過

客戶端程式碼:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>


    <script src="Scripts/jquery-1.7.1.min.js"></script>
    <script src="Scripts/jquery.signalR-2.2.1.min.js"></script>
    <script src="signalr/js"></script>
    <script>
        //手動代理
        //var conn = $.hubConnection();  //初始化連線
        //$(function () {
        //   var proxy=  conn.createHubProxy("MyHub");  //獲取服務代理
        //   proxy.on("clientHello", function (data,index) {  //定義可供伺服器呼叫的客戶端方法clientHello,該方法包含兩個引數
        //       console.log("伺服器呼叫客戶端程式碼");
        //   });
        //   conn.start().done(function (data) {  //當客戶端連線上伺服器的時候執行的方法
        //       proxy.invoke("ServerHello");  //執行伺服器端的方法ServerHello,此方法沒有引數
               
        //   });
        //});




        //自動代理
        var proxy = $.connection.myHub;  //獲取代理
        var id;  //客戶端連線伺服器時伺服器動態分配的connectionoid
        proxy.client.clientHello = function (data, index) { //定義可供伺服器呼叫的客戶端方法
            console.log("伺服器呼叫客戶端程式碼");
        }
        proxy.client.getConnectionID = function (connectionid) {  //定義可供伺服器呼叫的客戶端方法getConnectionID,該方法包含一個引數
            $("#lblid").text(connectionid);
            id=connectionid;
        }
        proxy.client.getServerContent = function (data) {  //定義可供伺服器呼叫的客戶端方法getServerContent,該方法包含一個引數 
            $("#history").val(data);
        }
        $.connection.hub.start().done(function () {  //當客戶端連線上了伺服器時候可以執行的程式碼
            proxy.server.serverHello("呼叫伺服器介面", 20);  //呼叫伺服器方法serverHello,伺服器端必須定義一個serverHello方法,該方法包含兩個引數
        });
        function sendSMG() {
            var content = $("#content").val();
            if (content != "") {
                proxy.server.serverSend(content, id);  //呼叫伺服器端的方法send,伺服器端必須定義一個Send的方法,該方法包含content和id兩個引數
            }
        }

    </script>
</head>
<body>
    <label id="lblid"></label>
    <p>
        <textarea id="history"></textarea>
    </p>
    <p>
        定向傳送:<br />
        <input type="text" id="content" /><br />
        <input type="button" value="傳送" onclick="sendSMG()" />
    </p>
</body>
</html>

注意上面紫色部分的js程式碼,因為集線器模式前端程式碼初始化連結的時候分為自動代理模式和手動代理模式,如果是手動代理模式,則只需要引用  <script src="Scripts/jquery-1.7.1.min.js"></script>,    <script src="Scripts/jquery.signalR-2.2.1.min.js"></script>這兩個指令碼,如果是自動代理模式,伺服器你會自動產生一個js指令碼,如上面我引用了 <script src="signalr/js"></script>這個指令碼,實際上這個指令碼只是在執行的時候伺服器自動給生成的,在編輯程式碼的時候是不存在這個指令碼程式碼的,

手動代理的時候,客戶端在呼叫伺服器端的函式的時候是沒辦法傳引數的

執行結果截圖如下:


在寫這篇部落格之前,我是看了一個大神的部落格進行學習的,這是他的部落格地址http://www.cnblogs.com/huangxincheng/p/5280630.html,我的這篇部落格只是一篇學習記錄,更詳細的內容可以參考http://www.cnblogs.com/huangxincheng/p/5280630.html這篇部落格