1. 程式人生 > >C#工作總結(一):Fleck的WebSocket使用

C#工作總結(一):Fleck的WebSocket使用

一.引子(Foreword)

      最近公司裡面要做窗體和網頁互動的功能。網上找了一下資料,這裡做一個簡單的擴充和整理,部分內容可能是摘自其他部落格,這裡會註明出處和原文地址供大家和自己日後查閱。

二.基礎知識(Foundation)

(1). WebSocket介紹

       WebSocket協議是基於TCP的一種新的網路協議。它實現了瀏覽器與伺服器全雙工(full-duplex)通訊——允許伺服器主動傳送資訊給客戶端。(

(2).瀏覽器對WebSocket的支援

瀏覽器

支援情況

Chrome谷歌瀏覽器

Chrome version 4+支援

Firefox火狐瀏覽器

Firefox version 5+支援

IE微軟瀏覽器

IE version 10+支援(我們一般win7自帶的是IE11

Safari蘋果瀏覽器

IOS 5+支援

Android Brower安卓瀏覽器

Android 4.5+支援

(3). WebSocket伺服器支援

廠商

應用伺服器

備註

IBM

WebSphere

WebSphere 8.0以上版本支援,7.X之前版本結合MQTT支援類似的HTTP長連線

甲骨文

WebLogic

WebLogic 12c 支援,11g以及10g版本通過HTTP Publish支援類似的HTTP長連線

微軟

IIS

IIS 7.0+支援

Apache

Tomcat

Tomcat 7.0.5+支援

Jetty

Jetty 7.0+支援

(4). Web前端知識概要

<1>. 物件建立(呼叫WebSocket的建構函式)

  1)函式原型:     

Constructor(DOMString url,[DOMString protocols]);

  2)說明:url為WebSocket伺服器的地址,protocols為發起握手的協議名稱,為可選擇項。

<2>. 介面及函式方法(WebSocket的介面的定義

  1)函式原型:

InterfaceWebSocket:EventTarget{
	readonly attribute DOMString url;
	//readyState狀態值
	Const unsigned short CONNECTING=0;
	Const unsigned short OPEN=1;
	Const unsigned short CLOSING=2;
	Const unsigned short CLOSED=3;
	readonly attribute unsigned short readyState;
	readonly attribute unsigned long bufferedAmount;
	//監聽網路狀態的事件監聽器屬性
	[TreatNonCallableAsNull] attribute Function? onopen;
	[TreatNonCallableAsNull] attribute Function? onerror;
        [TreatNonCallableAsNull] attribute Function? onclose;
	readonly attribute DOMString extensions;
	readonly attribute DOMString protocol;
	//關閉網路連線的方法
	void close([Clamp] optional unsigned short code,optional DOMString reason);
	//接受伺服器訊息的事件監聽器函式
	[TreatNonCallableAsNull] attribute Function? onmessage;
	attribute DOMString binaryType;
	void send(DOMString data);
	void send(ArrayBuffer data);
	void send(Blob data);
};

  2)說明:

        【1】. 兩個方法:

            ● send():向遠端伺服器傳送資料

            ● cosle():關閉該WebSocket

        【2】. 個重要的事件監聽器屬性:

            ● onopen:WebSocket建立網路連線的時候觸發該事件

            ● onerror:當網路連接出現問題的時候觸發該事件

            ● onclose:WebSocket被關閉的時候觸發該事件

            ● onmessage:當WebSocket接受到遠端伺服器的資料的時候觸發該事件

                    注意:1. 上面的四個函式名均為小寫,大小寫時敏感的;                              2. onmessage 繫結一個型為 function(event){} 的函式這樣就可以通過event.data來獲得返回的資料;

        【3】. readyState屬性,用於返回WebSocket所處的狀態:

            ● CONNECTING(數值0):WebSocket正在嘗試與伺服器建立連線

        ●OPEN(數值1):WebSocket與伺服器已經建立連線

            ● CLOSING(數值2:WebSocket正在關閉與伺服器的連線

            ● CLOSED(數值3:WebSocket已經關閉了與伺服器的連線

<3>. 使用WebSocket4

  1)將相關的定義函式繫結到上面4個監聽事件中;

  2)呼叫WebSocket的建構函式,給定一個url來初始化一個WebSocket物件;

  3)通過send()方法來發送資料;

  4)在有必要的時候可以用close()來關閉監聽;

(4).客戶端知識概要

<1>. 梗概

        我們可以通過基礎的Socket通訊來實現和網頁的相互通訊。但由於只有在.net Framework4.5以及4.5以上的版本對WebSocket通訊的資料解析才有相關的類來支援。所以解析資料寫起來十分的繁瑣,所以我們使用第三方的庫來完成低版本.net框架中的通訊。如果有時間我也會寫一篇有關socket來進行通訊及解析資料的文章。

        下來我看看用的軟體和相關的技術知識。

<2>. .Net不同WebSocket庫的比較

         我這裡找了一下網上的資料,如下連結,如果僅僅是要從網頁傳送訊息到伺服器,那麼我這邊使用Flerk。

<3>. Fleck的原始碼下載以及說明文件

        原始碼可以從網上下載,這裡我給出連結:原始碼下載

        點選頁面中的Clone or download -> Download ZIP,如下圖一

一.引子(Foreword)

        對於怎麼使用直接看說明文件,非常簡單,這裡博主就不多說了。(博主都寫到晚上1點了T T)

三.程式碼(Code)

(1). Web網頁端程式碼

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>WebSocket測試</title>
    <style>
        .div1
        {
            height:88px;   
            width:173px;
            border:1px solid blue;
            margin:auto;
        }
        h4
        {
            margin:auto;
        }
    </style>
    <script>
        var webSocket = {};
        //建立websockt
        function CreateWebSocket() {
            webSocket = new WebSocket("ws://127.0.0.1:30000");
            webSocket.onopen = WebSokectOnOpen;
            webSocket.onmessage = WebSocketOnMessage;
            webSocket.onclose = WebSocketOnClose;
        };

        //建立連線事件
        function WebSokectOnOpen() {
            alert("已經開啟連線!");
            webSocket.Send("WebSocketCreate Success!");
        };

        //監聽事件
        function WebSocketOnMessage(event) {
            //監聽來自客戶端的資料
            alert(event.data);
        };

        function WebSocketOnClose() {
            //監聽來自客戶端的資料
            alert('和伺服器斷開連線');
        };

        //傳送事件
        function WebSocketSendMsg() {
            //獲取text中的值
            var text = document.getElementById("Text1").value;
            //傳送到伺服器
            webSocket.send(text);
        };
    </script>
</head>
<body onload="CreateWebSocket()">
    <div class="div1">
        <h4>CSDN部落格</h4>
        <h4>By:LoveMiw</h4>
        <input type="text" id="Text1" />
        <input type="button" onclick="WebSocketSendMsg()" value="傳送資料" />
    </div>
</body>
</html>
(2). 服務端C#程式碼
//上面是程式生成的using
using Fleck;

namespace WebSocketTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //客戶端url以及其對應的Socket物件字典
            IDictionary<string, IWebSocketConnection> dic_Sockets = new Dictionary<string, IWebSocketConnection>();
            //建立

            WebSocketServer server = new WebSocketServer("ws://0.0.0.0:30000");//監聽所有的的地址
            //出錯後進行重啟
            server.RestartAfterListenError = true;

            //開始監聽
            server.Start(socket =>
            {
                socket.OnOpen = () =>   //連線建立事件
                {
                    //獲取客戶端網頁的url
                    string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                    dic_Sockets.Add(clientUrl, socket);
                    Console.WriteLine(DateTime.Now.ToString() + "|伺服器:和客戶端網頁:" + clientUrl + " 建立WebSock連線!");
                };
                socket.OnClose = () =>  //連線關閉事件
                {
                    string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                    //如果存在這個客戶端,那麼對這個socket進行移除
                    if (dic_Sockets.ContainsKey(clientUrl))
                    {
                        //注:Fleck中有釋放
                        //關閉物件連線 
                        //if (dic_Sockets[clientUrl] != null)
                        //{
                            //dic_Sockets[clientUrl].Close();
                        //}
                        dic_Sockets.Remove(clientUrl);
                    }
                    Console.WriteLine(DateTime.Now.ToString() + "|伺服器:和客戶端網頁:" + clientUrl + " 斷開WebSock連線!");
                };
                socket.OnMessage = message =>  //接受客戶端網頁訊息事件
                {
                    string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                    Console.WriteLine(DateTime.Now.ToString() + "|伺服器:【收到】來客戶端網頁:" + clientUrl + "的資訊:\n" + message);
                };
            });

            Console.ReadKey();
            foreach (var item in dic_Sockets.Values)
            {
                if (item.IsAvailable == true)
                {
                    item.Send("伺服器訊息:" + DateTime.Now.ToString());
                }
            }
            Console.ReadKey();

            //關閉與客戶端的所有的連線
            foreach (var item in dic_Sockets.Values)
            {
                if (item != null)
                {
                    item.Close();
                }
            }

            Console.ReadKey();
        }
    }
}

四. 結束語(Ending)

(1). 在Fleck上面下載的原始碼在放到工程中的時候似乎會報錯,只要重新把所有的.cs按它原來的結構新增到一個新的工程中在編譯就可以通過;

(2). 本文主要是用作記錄成長曆程的,還有這個WebSocket實踐性比較強,所以還是要自己動手去試試。所以部落格主由於在時間精力不是很的情況下就不去過多的強調程式碼了。如果真的需要可以下載我上面程式碼的原工程。最後我把Fleck的包也給一下吧。

(3).如果本文給您有什麼作用的話,轉發一下或給一個贊都是給我極大的支援。我排版包括那個頭上的圖片,都花了很多的經歷去製作和整理出來的。如果要轉載本文,請註明出處。晚安。2018年5月9日,凌晨。



one love for coding