ga('set', 'anonymizeIp', 1);
Categories: C#Coding

[C#] Websocket 異步連接實作 UI操作

Share

除了http request之外,websocket時常被用來進行常鏈接的網路功能實作。

本篇文章講述如何使用C# WebSocketSharp實作websocket功能。

Websocket Class設計

引用library

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebSocketSharp;
namespace MyWebSocket
{
    // 下方內容均在此
}

沒有WebSocketSharp的人記得要先去擴充庫下載。

筆者使用的是能夠自訂header的版本:websocket-sharp-customheaders
Install-Package websocket-sharp-customheaders
下方會解釋原因及使用方法。

創建websocket class

class webSocket
{
    private WebSocket ws;
    public event EventHandler<returnWebSocketMsg> WebSocketEventNotify;
}

宣告WebSocket ws。

宣告事件Handler,用來對接收websocket訊息後發出通知。

創建設定websocket

public void setUpWebsocket(string userID, string ip, string port){
    ws = new WebSocket("ws://" + ip + ":" + port + "/iptWeb/socketServer");
    //GC.Collect();
    ws.CustomHeaders = new Dictionary<string, string>
    {
        { "UserID", userID }
    };
    ws.OnOpen += Ws_OnOpen; ;
    ws.OnMessage += Ws_OnMessage;
    ws.OnError += Ws_OnError;
    ws.OnClose += Ws_OnClose;
}

上方程式碼中,使用該先帶入ip, port, (UserID),進行連線設定。

這邊有個小技巧,由於預設的WebSocketSharp library並無法簡單自訂連線header,
所以我們要去下載websocket-sharp-customheaders。
https://www.nuget.org/packages/websocket-sharp-customheaders

指令安裝:
Install-Package websocket-sharp-customheaders

ws.CustomHeaders = new Dictionary
{
    { "UserID", userID }
};

上方程式碼及為自訂連線header。
更詳細使用方式如下圖:

server連線資料設定完後,創建websocket事件,其中包含:
OnOpen: websocket開啟。
OnMessage: websocket訊息進入。
OnError: websocket發生錯誤。
OnClose: websocket關閉。

異步連接/斷連

public void connectToWebSocket()
{
    ws.ConnectAsync();
}

public void disconnectFromWebSocket()
{
    ws.OnOpen -= Ws_OnOpen;
    ws.OnMessage -= Ws_OnMessage;
    ws.OnError -= Ws_OnError;
    ws.OnClose -= Ws_OnClose;
    ws.Close();
    ws = null;
}

我們所使用的library支援異步連接,讓連接在程式背景執行,就不會干涉UI行為。

當斷連時,我們必須將監聽的事件移除,讓下次重新連線時重新加入事件。
並且清空物件。

websocket事件接收

private void Ws_OnOpen(object sender, EventArgs e)
{
    Console.WriteLine("Connect success!");
}

private void Ws_OnMessage(object sender, MessageEventArgs e)
{
    Console.WriteLine(e.Data);
    returnWebSocketMsg webSocketNotify = new returnWebSocketMsg();
    webSocketNotify.returnResult = e.Data;
    OnWebSocketEventNotify(webSocketNotify);
}

private void Ws_OnError(object sender, ErrorEventArgs e)
{
    Console.WriteLine("ERROR:" + e.Exception);
}

private void Ws_OnClose(object sender, CloseEventArgs e)
{
    Console.WriteLine("CLOSE:" + e.Reason);
}

這段程式碼主要針對websocket事件做接收後的行為。

筆者的程式是在有訊息進入時將data帶入class變數中(用來回傳給UI),
並發出事件。

發出事件

protected virtual void OnWebSocketEventNotify(returnWebSocketMsg e)
{
    EventHandler<returnWebSocketMsg> webSocketEventNotify = WebSocketEventNotify;
    if (webSocketEventNotify != null)
    {
        webSocketEventNotify(this, e);
    }
}

將OnMessage收到的資料帶入事件中發出。

定義class變數

public class returnWebSocketMsg : EventArgs
{
    public string returnResult { get; set; }
}

設定回傳訊息為string。


UI接收事件設定

引用websocket class

using MyWebSocket

初始化物件

webSocket newconnection = new webSocket();

在form load時加入事件並新增接收事件後之行為

private void Form_Load(object sender, EventArgs e)
{
    newconnection.WebSocketEventNotify += Newconnection_WebSocketEventNotify;
}

private void Newconnection_WebSocketEventNotify(object sender, webSocket.returnWebSocketMsg e)
{
    webSocketMsgIn(sender, e);
}

下方新增事件行為是在上方新增+=事件時按下tab會自動帶出。

這邊我們將事件中的行為改寫為呼叫webSocketMsgIn callback 並帶入事件本身(sender)以及data內容(e)。

UI連線

newconnection.setUpWebsocket(userID, serverIP, serverPort);
newconnection.connectToWebSocket();

這邊就是呼叫我們在class中的連線設定及連線。

可綁定在Button事件中(或是其他任何事件)。

UI斷線

newconnection.disconnectFromWebSocket();

事件callback

private void webSocketMsgIn(object sender, webSocket.returnWebSocketMsg e)
{
    // 針對websocket傳入之string設計行為     
}

Jys

Published by
Jys

Recent Posts

[python] Flask Create RESTful API

This article gi... Read More

3 年 前發表

[Javascript] 新增/刪除JSON中key值

在web訊息交換常會需要對JS... Read More

3 年 前發表

[JAVA] SQL Server Connection

本文介紹JAVA連線SQL s... Read More

3 年 前發表