.Net SuperSocket 实现WebSocket服务端与客户端通信

本文详细介绍如何在VS2017中创建WinForm项目并集成SuperWebSocketNETServer,实现WebSocket服务端功能,包括log4net配置、界面设计、代码实现及客户端连接测试。服务端能处理客户端连接、接收消息、发送消息等操作,并通过JSON帮助类解析消息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、项目创建

1、VS2017创建winform项目

2、Nuget中搜索安装 SuperWebSocketNETServer

二、WebSocket服务端功能实现

1、由于有使用到log4net,在开始实现功能前,需要对log4net进行相关设置,设置参考https://blog.youkuaiyun.com/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" onclick="connectionServer();">连接</button>
        <button type="button" onclick="DisconnectionServer()">断开</button>
    </div>
    <div>
        <button type="button" onclick="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>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值