除了http request之外,websocket時常被用來進行常鏈接的網路功能實作。
本篇文章講述如何使用C# WebSocketSharp實作websocket功能。
Websocket Class設計
引用library
1 2 3 4 5 6 7 8 9 10 11 |
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
1 2 3 4 5 |
class webSocket { private WebSocket ws; public event EventHandler<returnWebSocketMsg> WebSocketEventNotify; } |
宣告WebSocket ws。
宣告事件Handler,用來對接收websocket訊息後發出通知。
創建設定websocket function
1 2 3 4 5 6 7 8 9 10 11 12 |
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; } |
上方程式碼中,使用該function先帶入ip, port, (UserID),進行連線設定。
這邊有個小技巧,由於預設的WebSocketSharp library並無法簡單自訂連線header,
所以我們要去下載websocket-sharp-customheaders。
https://www.nuget.org/packages/websocket-sharp-customheaders
指令安裝:
Install-Package websocket-sharp-customheaders
1 2 3 4 |
ws.CustomHeaders = new Dictionary { { "UserID", userID } }; |
上方程式碼及為自訂連線header。
更詳細使用方式如下圖:
server連線資料設定完後,創建websocket事件,其中包含:
OnOpen: websocket開啟。
OnMessage: websocket訊息進入。
OnError: websocket發生錯誤。
OnClose: websocket關閉。
異步連接function/斷連function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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事件接收function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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),
並發出事件。
發出事件function
1 2 3 4 5 6 7 8 |
protected virtual void OnWebSocketEventNotify(returnWebSocketMsg e) { EventHandler<returnWebSocketMsg> webSocketEventNotify = WebSocketEventNotify; if (webSocketEventNotify != null) { webSocketEventNotify(this, e); } } |
將OnMessage收到的資料帶入事件中發出。
定義class變數
1 2 3 4 |
public class returnWebSocketMsg : EventArgs { public string returnResult { get; set; } } |
設定回傳訊息為string。
UI接收事件設定
引用websocket class
1 |
using MyWebSocket |
初始化物件
1 |
webSocket newconnection = new webSocket(); |
在form load時加入事件並新增接收事件後之行為
1 2 3 4 5 6 7 8 9 |
private void Form_Load(object sender, EventArgs e) { newconnection.WebSocketEventNotify += Newconnection_WebSocketEventNotify; } private void Newconnection_WebSocketEventNotify(object sender, webSocket.returnWebSocketMsg e) { webSocketMsgIn(sender, e); } |
下方新增事件行為function是在上方新增+=事件時按下tab會自動帶出。
這邊我們將事件中的行為改寫為呼叫webSocketMsgIn callback function並帶入事件本身(sender)以及data內容(e)。
UI連線
1 2 |
newconnection.setUpWebsocket(userID, serverIP, serverPort); newconnection.connectToWebSocket(); |
這邊就是呼叫我們在class中的連線設定及連線function。
可綁定在Button事件中(或是其他任何事件)。
UI斷線
1 |
newconnection.disconnectFromWebSocket(); |
事件callback function
1 2 3 4 |
private void webSocketMsgIn(object sender, webSocket.returnWebSocketMsg e) { // 針對websocket傳入之string設計行為 } |
留言