UnityWebGL調研(6) SignalR通信

SignalR原本就是網頁支持的技術,底層應該是用WebSocket的。

但是項目打包成WebGL後,發現無法獲取服務端的告警信息,需要另外研究一下了。

Unity裏面的SignalR是用BestHTTP實現的。

 

一、搭建服務端

參考:SignalR如何搭建SelfHost服務端(C#)

我用控制檯引用程序搭建服務端,先創建控制檯項目,然後加上需要的庫

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
using Owin;
using Microsoft.Owin.Cors;


namespace SignalRServer
{
    class Program
    {
        static void Main(string[] args)
        {
            var uri = "http://127.0.0.1:9999";
            using (Microsoft.Owin.Hosting.WebApp.Start<Startup>(uri))
            {
                Console.WriteLine(string.Format("Server stared on {0}", uri));
                Console.ReadLine();
            }
        }
    }

    class Startup
    {
        static Hub hub;
        public void Configuration(IAppBuilder app)
        {
            //app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            //var configuration = new HubConfiguration();
            //configuration.EnableDetailedErrors = true;
            //app.MapSignalR("/signalr", configuration);
            //hub = new MyHub();

            app.Map("/realtime", map =>
            {
                map.UseCors(CorsOptions.AllowAll);
                var config = new HubConfiguration()
                {
                    EnableJSONP = true,
                    //EnableJavaScriptProxies = false
                };
#if DEBUG
                config.EnableDetailedErrors = true;
#endif
                map.RunSignalR(config);
            });
        }
    }

    public class MyHub : Hub
    {
        public override Task OnConnected()
        {
            Console.WriteLine("有客戶端連接");
            return base.OnConnected();
        }

        //服務端的方法,客戶端可以去調用
        public void Send(string name, string message)
        {
            Console.WriteLine("[{0}]Send:{1}", name, message);
            //string name = "BG";
            //調用客戶端的方法sendMessage(string s1,string s2);      
            Clients.All.AddMessage(name, message);
        }
    }
}

二、Html客戶端

參考《ASP.NET SignalR編程實戰》,書本代碼地址:https://resources.oreilly.com/examples/9780735683884-files/

參考代碼:https://www.haolizi.net/example/tags_SignalR_1.html

<!DOCTYPE html>
<html>
<head>
    <title>SignalR Simple Chat</title>
    <style type="text/css">
        .container {
            background-color: #99CCFF;
            border: thick solid #808080;
            padding: 20px;
            margin: 20px;
        }
    </style>
</head>
<body>
    <div class="container">
        <input type="text" id="message" />
        <input type="button" id="sendmessage" value="Send" />
        <input type="hidden" id="displayname" />
        <ul id="discussion"></ul>
    </div>
    <!--Script references. -->
    <!--Reference the jQuery library. -->
    <script src="Scripts/jquery-1.6.4.min.js"></script>
    <!--Reference the SignalR library. -->
    <script src="Scripts/jquery.signalR-2.0.3.min.js"></script>
    <!--Reference the autogenerated SignalR hub script. -->
    <script src="http://127.0.0.1:9999/realtime/hubs"></script>
    <!--Add script to update the page and send messages.-->
    <script type="text/javascript">
        $(function () {
        //Set the hubs URL for the connection
            //$.connection.hub.url = "http://localhost:8080/signalr";
            $.connection.hub.url = "http://127.0.0.1:9999/realtime";
            // Declare a proxy to reference the hub.
            var chat = $.connection.myHub;

            // Create a function that the hub can call to broadcast messages.
            chat.client.addMessage = function (name, message) {
                // Html encode display name and message.
                var encodedName = $('<div />').text(name).html();
                var encodedMsg = $('<div />').text(message).html();
                // Add the message to the page.
                $('#discussion').append('<li><strong>' + encodedName
                    + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
            };
            // Get the user name and store it to prepend to messages.
            $('#displayname').val(prompt('Enter your name:', ''));
            // Set initial focus to message input box.
            $('#message').focus();
            // Start the connection.
            $.connection.hub.start().done(function () {
                $('#sendmessage').click(function () {
                    // Call the Send method on the hub.
                    chat.server.send($('#displayname').val(), $('#message').val());
                    // Clear text box and reset focus for next comment.
                    $('#message').val('').focus();
                });
            });
        });
    </script>
</body>
</html>

在哪裏設置url裏面花了些時間,網上找的例子都是不需要設置url的,是直接通過aps.net啓動網頁,然後使用的。

而這個是單獨的html頁面啓動的,也不用放到iis裏面,就是一個獨立的html客戶端。

三、Unity客戶端

我用的BestHttp是1.9.9 (2016.02.16)。

3年多了啊,應該更新一下了。

Unity代碼

using System;

using UnityEngine;

using BestHTTP.SignalR;
using BestHTTP.SignalR.Hubs;
using BestHTTP.SignalR.Messages;
using BestHTTP.SignalR.JsonEncoders;
using BestHTTP.Examples;
using UnityEngine.UI;
using BestHTTP;

public class MyHubSample : MonoBehaviour
{
    public InputField InputFieldUrl;
    public InputField InputFieldName;
    public InputField InputFieldMessage;
    public Text TextReceived;
    public string URI = "http://127.0.0.1:9999/realtime";

    /// <summary>
    /// The SignalR connection instance
    /// </summary>
    Connection signalRConnection;

    private MyHub myHub;

    void Start()
    {
        //StartHub();
    }

    void OnDestroy()
    {
        StopHub();
    }

    public void StartHub()
    {
        HTTPManager.Setup();
        HTTPManager.Logger.Level = BestHTTP.Logger.Loglevels.All;
        Debug.Log("HTTPManager.Logger.Level:" + HTTPManager.Logger.Level);

        TextReceived.text = "";

        if (InputFieldUrl)
        {
            URI = InputFieldUrl.text;
        }

        myHub = new MyHub();
        myHub.received += (msg) => { TextReceived.text += msg + "\n"; };

        // Create the SignalR connection, passing all the three hubs to it
        //signalRConnection = new Connection(URI, demoHub, typedDemoHub, vbDemoHub);
        signalRConnection = new Connection(new Uri(URI), myHub);

        // Switch from the default encoder to the LitJson Encoder becouse it can handle the complex types too.
        signalRConnection.JsonEncoder = new LitJsonEncoder();

        // Call the demo functions when we successfully connect to the server
        signalRConnection.OnConnected += (connection) =>
        {
            Debug.Log("signalRConnection.OnConnected");
            //myHub.Send("Unity", "Hello");
            Send();
        };
        // Start opening the signalR connection
        signalRConnection.Open();
    }

    public void StopHub()
    {
        // Close the connection when we are closing this sample
        if(signalRConnection!=null)
            signalRConnection.Close();
    }

    public void Send()
    {
        string user = "Unity";
        if (InputFieldName)
        {
            user = InputFieldName.text;
        }
        string messag = "Hello";
        if (InputFieldMessage)
        {
            messag = InputFieldMessage.text;
        }

        myHub.Send(user, messag);
    }
}

class MyHub : Hub
{
    public event Action<string> received;

    public MyHub()
        : base("myHub")
    {

        // Setup server-called functions
        base.On("AddMessage", AddMessage);
    }

    private void AddMessage(Hub hub, MethodCallMessage methodCall)
    {
        string typedEchoClientResult = string.Format("{0} #{1} triggered!", methodCall.Arguments[0], methodCall.Arguments[1]);
        string msg = methodCall.Arguments[1]+"";
        Debug.Log("MyHub.AddMessage:" + typedEchoClientResult);
        if (received != null)
        {
            received(msg);
        }
    }

    public void Send(string name, string msg)
    {
        Debug.Log("MyHub.Send:" + name + "," + msg);
        base.Call("Send", name, msg);
    }
}

結果來說,exe打包是沒問題的,webgl打包出錯了。

發送的ws以及httprequest的地址有問題,上面的地址ws和GET的地址,仔細觀察會發現有%252F,這樣的其實是/。

/  => %2F => %252F。

%25是 %,會發現地址裏面很多%25,其實就是多轉換了一次。

BestHTTP_WebSocket.jslib修改:

BestHTTP_WebRequest.jslib修改:

文件位置

然後在打包就可以了。

搞了一整天,弄來弄起,結果發現BestHttp插件本身有問題。。。。。。。,難道16年時需要這麼寫的,而現在不用了,變成多此一舉了。。。。

估計升級一下插件的版本可能也可以解決這個問題,明天有空試試。

哎,一天下來,大體明白了SinalR的協商過程。一點點收穫。

-----------------------------------------------------------------------------------------------------------------------

在淘寶上買了個1.12.5的版本,1.12.5 (2019.09.03),2塊錢.....

看代碼,確實把我昨天改的那部分改好了。

打包webgl,測試,沒問題。

果然應該不斷與時俱進的。

出了問題,除了考慮自己解決外,要考慮插件有沒有新版本。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章