Electron+HTML做界面,C#做后台(三)使用Socket组件StriveEngin实现通讯

Electron 和 C#控制台程序通信

Electron+HTML做界面,C#做后台(二) 中简单说了线如何创建C#程序,并启动Electron程序,那么这节就说说两者之间怎么通信【C#使用StriveEngine.dll】或者百度相关信息

打开前面创建的项目

1.将debug目录下的 electronApp复制一份到当前的项目目录,

在这里插入图片描述

与vs创建的 bin目录同级
在这里插入图片描述

2.在vs项目中 包含electronApp目录文件(不要包含node_modules目录,文件太多)

在这里插入图片描述

3.继续选中文件,并选中右键属性,复制到输出目录在这里插入图片描述

4. 添加类创建 Socket服务 ,类名称 Services.cs【记得添加引用】

using StriveEngine;
using StriveEngine.Core;
using StriveEngine.Tcp.Server;
using System;
using System.Diagnostics;
using System.Net;
using System.Text;
using System.Windows.Forms;

namespace ElectronHTMlCSharp
{
    /// <summary>
    /// 在本地开启服务,监听指定端口
    /// </summary>
    public class Services
    {
        public static Services services;

        private ITcpServerEngine SockterServerEngine;
        private bool IsSocketServerInitialized;
        public void StartServer()
        {
            try
            {
                if (SockterServerEngine == null)
                {
                    var port = AppTools.Get("port");
                    var _port = port == null || port.Length <= 0 ? 9909 : int.Parse(port);
                    SockterServerEngine = NetworkEngineFactory.CreateTextTcpServerEngine(_port, new DefaultTextContractHelper("\0"));//DefaultTextContractHelper是StriveEngine内置的ITextContractHelper实现。使用UTF-8对EndToken进行编码。 
                }
                //判断 相关的监听事件是否注册
                if (IsSocketServerInitialized)
                {
                    SockterServerEngine.ChangeListenerState(true);
                }
                else
                {
                    InitializeTcpServerEngine();
                }

                //this.ShowListenStatus();
            }
            catch (Exception ee)
            {
                Console.WriteLine(ee.Message);
                if (ee.Message.IndexOf("there's one StriveEngine server instance running") >= 0)
                {
                    var res = MessageBox.Show("已打开一个实例或者前面实例的进程为未完全退出,是否重启?\r\n是:重启\r\n否:关闭\r\n取消:不做任何处理", "警告", MessageBoxButtons.YesNoCancel);
                    if (DialogResult.Yes == res)
                    {
                        Application.ExitThread();
                        Application.Exit();
                        Application.Restart();
                        Process.GetCurrentProcess().Kill();
                    }
                    else if (DialogResult.No == res)
                    {
                        Application.ExitThread();
                        Application.Exit();
                        Process.GetCurrentProcess().Kill();
                    }
                }
            }
            services = this;
        }
        /// <summary>
        /// 为 socket 注册 服务事件
        /// </summary>
        private void InitializeTcpServerEngine()
        {
            //客户端连接数量变化时,触发事件
            SockterServerEngine.ClientCountChanged += new CbDelegate<int>(ClientCountChage);
            //客户端与服务端建立连接时, 触发事件
            SockterServerEngine.ClientConnected += new CbDelegate<IPEndPoint>(ClientConnected);
            //客户端断开连接时, 触发事件
            SockterServerEngine.ClientDisconnected += new CbDelegate<IPEndPoint>(ClientDisconnected);
            //接受消息,触发事件
            SockterServerEngine.MessageReceived += new CbDelegate<IPEndPoint, byte[]>(MessageReceived);

            //初始化tcp服务对象
            SockterServerEngine.Initialize();
            //标记tcp 服务已经初始化
            IsSocketServerInitialized = true;
        }

        /// <summary>
        ///  客户端连接数量变化时,触发事件
        /// </summary>
        private void ClientCountChage(int count)
        {
            Console.WriteLine("已连接数量" + count);
        }

        /// <summary>
        /// 客户端与服务端建立连接时, 触发事件
        /// </summary>
        /// <param name="IPEndPoint"></param>
        private void ClientConnected(IPEndPoint iPEndPoint)
        {
            var msg = string.Format("{0} 上线", iPEndPoint);
            Console.WriteLine(msg);
        }

        /// <summary>
        /// 断开服务时, 触发事件
        /// </summary>
        /// <param name="iPEndPoint"></param>
        private void ClientDisconnected(IPEndPoint iPEndPoint)
        {
            var msg = string.Format("{0} 下线", iPEndPoint);
            Console.WriteLine(msg);
        }

        /// <summary>
        /// 接受消息,触发事件
        /// </summary>
        /// <param name="client"></param>
        /// <param name="bMsg"></param>
        private void MessageReceived(IPEndPoint client, byte[] bMsg)
        {
            var msg = Encoding.UTF8.GetString(bMsg); //消息使用UTF-8编码
            SendMsgToClient("接收到客户端消息:" + msg, client);
        }

        /// <summary>
        /// 发送消息到指定的客户端
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="client"></param>
        public void SendMsgToClient(string msg, IPEndPoint client)
        {
            var bMsg = System.Text.Encoding.UTF8.GetBytes(msg);//消息使用UTF-8编码
            client = client ?? (IPEndPoint)SockterServerEngine.GetClientList()[0];
            SockterServerEngine.SendMessageToClient(client, bMsg);
        }
    }
}

4.2在Program.cs文件的Main方法中调用 Services ,添加如下代码

    var ser = new Services();
    ser.StartServer();

最终如图

在这里插入图片描述

5.创建 js文件用于前端socket请求工具类

5.1在 electronApp目录下创建socket-helper.js

var top = top || {};

/**
 * 创建 sock实例并发送消息 ,短连接 ,发送一条消息之后就关闭
 * @param {any} ip 发送内容
 * @param {any} port 发送内容
 * @param {any} sendMsg 发送内容
 * @param {any} callGetMsg 得到消息的回调函数
 * @param {any} callOpen 连接之后服务端发送回 消息 执行的回调函数
 * @param {any} cllClose 关闭连接的回调函数,默认自动关闭
 */
function initSocket(ip, port, sendMsg,callGetMsg,callOpen,cllClose) {
    top.ip = top.ip || ip;
    top.port = top.port || port;
    var host = "ws://" + top.ip + ":" + top.port + "/"
    socket = new WebSocket(host);
    socket.onmessage = function (event) {
        if (typeof callGetMsg == "function")
            callGetMsg(event);
        if (typeof cllClose == "function") {
                cllClose(socket);
            } else {
            socket.close();
        }
    }
    socket.onopen = function (event) {
        if (typeof callOpen == "function")
            callOpen(event);
        socket.send(sendMsg);
    }
    return socket;
}

/**
 * 创建 sock实例并发送消息 ,短连接 ,发送一条消息之后就关闭
 * @param {any} sendMsg 发送内容
 * @param {any} callGetMsg 得到消息的回调函数
 * @param {any} callOpen 连接之后服务端发送回 消息 执行的回调函数
 * @param {any} cllClose 关闭连接的回调函数,默认自动关闭
 */
function initSockets(sendMsg, callGetMsg, callOpen, cllClose) {
    var host = "ws://" + top.ip + ":" + top.port + "/"
    socket = new WebSocket(host);
    socket.onmessage = function (event) {
        if (typeof callGetMsg == "function")
            callGetMsg(event);
        if (typeof cllClose == "function") {
            cllClose(socket);
        } else {
            socket.close();
        }
    }
    socket.onopen = function (event) {
        if (typeof callOpen == "function")
            callOpen(event);
        socket.send(sendMsg);
    }
    return socket;
}


/**
 * 创建 sock实例并发送消息 ,长连接
 * @param {any} sendMsg 发送内容
 * @param {any} callGetMsg 得到消息的回调函数
 * @param {any} callOpen 连接之后服务端发送回 消息 执行的回调函数
 * @param {any} cllClose 关闭连接的回调函数,默认自动关闭
 */
function initSocketLong(sendMsg, callGetMsg, callOpen, cllClose) {
    var host = "ws://" + top.ip + ":" + top.port + "/"
    socket = new WebSocket(host);
    socket.onmessage = function (event) {
        if (typeof callGetMsg == "function")
            callGetMsg(event);
        if (typeof cllClose == "function") {
            cllClose(socket);
        }
    }
    socket.onopen =  function (event) {
        if (typeof callOpen == "function")
            callOpen(event);
        sendMsg += (sendMsg.indexOf("?") > 0 ? "&" : "?") + "isLong=true";
        socket.send(sendMsg);
    }
    return socket;
}

5.2创建 socket页面调用 js文件 hander.js

/***
 * 依赖文件 socket-helper.js
 * */

//配置 通信信息
function getSocketConf() {
    return {
        ip: '127.0.0.1',
        port: '9909'
    }
}

///**
// * 发送请求,返回后端处理的数据
// * @param {any} action action!method?par1=1&par2=2&parn=n&....
// * @param {any} callback 后端返回的回调函数
// */
//function Hander(action, callback) {
//    var con = getSocketConf();
//    top.ip = !top.ip ? con["ip"] : top.ip;
//    top.port = !top.port ? con["port"] : top.port;
//    initSockets(action, callback);
//}

/**
 * 发送请求,返回后端处理的数据
 * @param {any} action action!method?par1=1&par2=2&parn=n&....
 * @param {any} callback 后端返回的回调函数
 */
function Hander(action, callback) {
    var con = getSocketConf();
    top.ip = !top.ip ? con["ip"] : top.ip;
    top.port = !top.port ? con["port"] : top.port;
   return initSockets(action, callback, null, function (event) {});
}

/**
 * 发送请求,返回后端处理的数据 长链接 
 * @param {any} action action!method?par1=1&par2=2&parn=n&....
 * @param {any} callback 后端返回的回调函数
 */
function HanderLong(action, callback) {
    var con = getSocketConf();
    top.ip = !top.ip ? con["ip"] : top.ip;
    top.port = !top.port ? con["port"] : top.port;
    return initSocketLong(action, callback, null, function (event) { });
}

创建好的目录如下

在这里插入图片描述

创建完两个 js文件之后一定记得 右键属性复制到输出目录

6之后我们需要在index.html页面上使用socket进行通信,添加如下代码

<!doctype html>
<html>
	<head>
		<title>hello Word</title>
	</head>
    <body>
        <h1>这是用Electron创建的程序,这个程序后面将会使用C#来实现数据逻辑处理</h1>
        <div>
            <input type="text" value="测试文字" id="text" />
            <input type="button" id="send" value="发送" />
            接受区域
            <div id="msg" style="width:100%;height:auto;border:1px solid #0094ff;">

            </div>
        </div>
        <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
        <script>if (typeof module === 'object') { top.$ = window.jQuery = window.$ = module.exports; };</script>
        <script src="socket-helper.js"></script>
        <script src="hander.js"></script>
        <script>
            $(function () {
                //侦听 发送按钮 事件,并将返C#端返回的数据 绑定到接受区域
                $("#send").on("click", function () {
                    var msg = $("#text").val();
                    Hander(msg, function (res) {
                        var html = $("#msg").html();
                        $("#msg").html(html + "<p>"+res.data+"</p>");
                    })
                });
            });
        </script>
    </body>
</html>

7.启动vs项目

在这里插入图片描述
在这里插入图片描述

*** 如此前后台就可以通行了,但是要注意 这个 websock框架对发送的字节大小有限制 ***

后面将会讲述如何通过webSoket ,执行C# 指定类的指定的方法 【使用反射实现

如果你已经迫不及待,那么请下载整个项目的源代码,代码已放置 GITHUB源码下载,上面有最新的效果图

如果觉得不错,请打赏我,或者用钱侮辱我~_~!

在这里插入图片描述

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