.Net SuperSocket 實現WebSocket服務端與客戶端通信

一、項目創建

1、VS2017創建winform項目

2、Nuget中搜索安裝 SuperWebSocketNETServer

二、WebSocket服務端功能實現

1、由於有使用到log4net,在開始實現功能前,需要對log4net進行相關設置,設置參考https://blog.csdn.net/liwan09/article/details/106266346

2、界面設置

 

3、實現功能代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;
using SuperWebSocket;
using log4net;
using Bosch.Rtns.Sockect.Model;
using Bosch.Rtns.Sockect.CommonUtils;

namespace Bosch.Rtns.Sockect
{
    public partial class frmMain : Form
    {
        private WebSocketServer webSocketServer;
        ILog loggerManager;
        Dictionary<WebSocketSession, string> socketSessionList = new Dictionary<WebSocketSession, string>();//記錄鏈接的客戶端數據

        public frmMain()
        {
            InitializeComponent();
        }
        /// <summary>
        /// load
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_Load(object sender, EventArgs e)
        {
            loggerManager=LogManager.GetLogger("Logger");
            txtIPAddress.Text = "127.0.0.1";
            txtPort.Text = "1414";
            btnEnd.Enabled = false;
        }
        /// <summary>
        ///開啓服務
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            string ipAddress = txtIPAddress.Text.Trim();
            string port = txtPort.Text.Trim();
            if (string.IsNullOrEmpty(ipAddress))
            {
                txtIPAddress.Focus();
                MessageBox.Show("請輸入IP地址!");
                return;
            }
            if (string.IsNullOrEmpty(port))
            {
                txtPort.Focus();
                MessageBox.Show("請輸入端口號!");
                return;
            }           
            webSocketServer = new WebSocketServer();
            webSocketServer.NewSessionConnected += Sockect_NewSessionConnected;
            webSocketServer.NewMessageReceived += Sockect_NewMessageReceived;
            webSocketServer.SessionClosed += Sockect_SessionClosed;
            if (!webSocketServer.Setup(ipAddress,Convert.ToInt32(port)))
            {
                txtLogInfo.Text += "設置Socket服務偵聽地址失敗!\r\n";
                loggerManager.Error("設置Socket服務偵聽地址失敗!\r\n");
                return;
            }
            if (!webSocketServer.Start())
            {
                txtLogInfo.Text += "啓動WebSocket服務偵聽失敗!\r\n";
                loggerManager.Error("啓動WebSocket服務偵聽失敗!\r\n");
                return;
            }
            txtLogInfo.Text += "Socket啓動服務成功!\r\n";
            loggerManager.Info("Socket啓動服務成功!\r\n");
            txtIPAddress.Enabled = false;
            txtPort.Enabled = false;
            btnStart.Enabled = false;
            btnEnd.Enabled = true;
        }
        /// <summary>
        /// 關閉服務
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnEnd_Click(object sender, EventArgs e)
        {
            if (webSocketServer != null)
            {
                webSocketServer.Stop();
                webSocketServer = null;
            }
            txtIPAddress.Enabled = true;
            txtPort.Enabled = true;
            btnStart.Enabled = true;
            btnEnd.Enabled = false;
        }

        /// <summary>
        /// 新的Socket連接事件
        /// </summary>
        /// <param name="session"></param>
        private void Sockect_NewSessionConnected(WebSocketSession session)
        {
            string logMsg = string.Format("{0} 與客戶端{1}創建新會話", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), GetwebSocketSessionName(session))+"\r\n";            
            this.Invoke(new Action(() =>
            {
                txtLogInfo.Text += logMsg;
            }));
            loggerManager.Info(logMsg);
            socketSessionList.Add(session, "");
        }
        /// <summary>
        /// 消息接收事件
        /// </summary>
        /// <param name="session"></param>
        /// <param name="value">接收的消息</param>
        private void Sockect_NewMessageReceived(WebSocketSession session, string value)
        {
            string logMsg = string.Format("{0} 從客戶端{1}接收新的消息:\r\n{2}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), GetwebSocketSessionName(session),value) + "\r\n";
            this.Invoke(new Action(() =>
            {
                txtLogInfo.Text += logMsg;
            }));
            loggerManager.Info(logMsg);
            ReceiveData receiveData = JsonHelper.ConvertToEntity<ReceiveData>(value);
            //退出登錄
            if (receiveData.MessageType == "3")
            {
                //調用weiapi接口,更新在線用戶的在線狀態
                socketSessionList.Remove(session);
                session.Close(SuperSocket.SocketBase.CloseReason.ClientClosing);//斷開連接
            }
            else
            {
                if(receiveData.MessageType == "4")//設備故障推送
                {
                    EquipmentFault equipmentFault = JsonHelper.ConvertToEntity<EquipmentFault>(receiveData.MessageContent);
                }
                else
                {
                    socketSessionList[session] = receiveData.MessageContent;//記錄app端的設備id
                }
            }
        }
        /// <summary>
        /// sockect客戶端斷開連接事件
        /// </summary>
        /// <param name="session"></param>
        /// <param name="value"></param>
        private void Sockect_SessionClosed(WebSocketSession session, SuperSocket.SocketBase.CloseReason value)
        {
            string logMsg = string.Format("{0} 與客戶端{1}的會話被關閉 原因:{2}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), GetwebSocketSessionName(session), value) + "\r\n";
            this.Invoke(new Action(() =>
            {
                txtLogInfo.Text += logMsg;
            }));
            loggerManager.Info(logMsg);
            socketSessionList.Remove(session);
        }
        /// <summary>
        /// 獲取連接的客戶端的ip地址
        /// </summary>
        /// <param name="webSocketSession"></param>
        private static string GetwebSocketSessionName(WebSocketSession webSocketSession)
        {
            string id= HttpUtility.UrlDecode(webSocketSession.SessionID);//獲取sessionid
            var remoteClient = webSocketSession.RemoteEndPoint;
            return remoteClient.Address + ":" + remoteClient.Port.ToString();
        }
        /// <summary>
        /// 發送消息
        /// </summary>
        /// <param name="session"></param>
        /// <param name="msg"></param>
        private void SendMessage(WebSocketSession session, string msg)
        {
            //向所有客戶端發送消息
            //foreach (var sendSession in session.AppServer.GetAllSessions())
            //{
            //    sendSession.Send(msg);
            //}
            session.Send(msg);//向指定的客戶端發送消息
        }
    }
}

 相關實體類代碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bosch.Rtns.Sockect.Model
{
    /// <summary>
    /// 設備故障信息
    /// </summary>
    public class EquipmentFault
    {
        /// <summary>
        /// 目標手機設備ID
        /// </summary>
        public string TargetPhoneID { get; set; }
        /// <summary>
        /// 故障發生時間
        /// </summary>
        public DateTime FaultTime { get; set; }
        /// <summary>
        /// 消息id
        /// </summary>
        public string MessageUID { get; set; }
        /// <summary>
        /// 消息標題
        /// </summary>
        public string MessageTitle { get; set; }
        /// <summary>
        /// 發送給App(消息類型)
        /// </summary>
        public string SubAPPname { get; set; }
        /// <summary>
        /// 故障等級 Low,Default,High,Emergent
        /// </summary>
        public string EmergenceLevel { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bosch.Rtns.Sockect.Model
{
    /// <summary>
    /// 接收的消息
    /// </summary>
    public class ReceiveData
    {
        /// <summary>
        /// 接收的消息類型 1:App端登錄  2:設備故障信息推送
        /// </summary>
        public string MessageType { get; set; }
        /// <summary>
        /// 消息內容
        /// </summary>
        public string MessageContent { get; set; }
    }
}

Json幫助類代碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Bosch.Rtns.Sockect.CommonUtils
{
    /// <summary>
    /// Json幫助類
    /// </summary>
    public class JsonHelper
    {
        /// <summary>
        /// object轉json
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ConvertObjToJson(object obj)
        {
            return JsonConvert.SerializeObject(obj);
        }
        /// <summary>
        /// Json字符串轉實體類數據
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="jsonValue"></param>
        /// <returns></returns>
        public static T ConvertToEntity<T>(string jsonValue)
        {
            return JsonConvert.DeserializeObject<T>(jsonValue);
        }
        /// <summary>
        /// Json字符串轉List<T>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="jsonValue"></param>
        /// <returns></returns>
        public static List<T> ConvertToList<T>(string jsonValue)
        {
            return JsonConvert.DeserializeObject<List<T>>(jsonValue);
        }
    }
}

4、客戶端代碼(html)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Web sockets test</title>
    <script src="jquery-min.js"></script>
</head>
<body>
    <div>
        服務器地址:<input type="text" id="serverAddress" value="127.0.0.1:4141" />
        <button type="button" οnclick="connectionServer();">連接</button>
        <button type="button" οnclick="DisconnectionServer()">斷開</button>
    </div>
    <div>
        <button type="button" οnclick="senMsg()">發送消息</button>
        <div>
            <textarea id="txtmsg" style="height:200px;width:300px"></textarea>
        </div>
    </div>
</body>
</html>
<script type="text/javascript">
    var ws;
    var SocketCreated = false;
    var isUserloggedout = false;
    var defaultMsg = "{\"MessageType\":\"\",\"MessageContent\":\"\"}";
    document.getElementById("txtmsg").value = defaultMsg;

    function connectionServer() {
        try {
            if ("WebSocket" in window) {
                ws = new WebSocket("ws://" + document.getElementById("serverAddress").value);
            }
            else if ("MozWebSocket" in window) {
                ws = new MozWebSocket("ws://" + document.getElementById("serverAddress").value);
            }
            SocketCreated = true;
            isUserloggedout = false;
        } catch (ex) {
            alert("連接失敗");
            return;
        }
    }

    function DisconnectionServer() {
        if (SocketCreated && (ws.readyState == 0 || ws.readyState == 1)) {
            SocketCreated = false;
            isUserloggedout = true;
            ws.close();
        }
    }

    function senMsg() {
        if (SocketCreated) {
            var msg = document.getElementById("txtmsg").value;
            ws.send(msg);
        }
    }
</script>

 

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