主頁 > 軟體設計 > 超級訊息轉換器

超級訊息轉換器

2021-11-14 13:26:45 軟體設計

之前實作的檢驗虛擬盒子雖然實作了串口轉TCP功能,但是缺乏設計,表現為設計太僵硬,只能固定兩三種轉換模式,而且隨著轉換增加復雜度太大,比如要實作某些儀器TCP不能跨網站做TCP直接跳板就難度大大增加,

虛擬盒子體現為代碼力,這次體現為設計力,

原始碼

虛擬盒子如下:
在這里插入圖片描述
新效果-TCP跳轉示例
在這里插入圖片描述
其他測驗
在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

為了解決設計不足導致的擴展困難,全新設計了超級轉換器,分享初版代碼,這次抽取了轉換器介面,和提取了委托,實作為一個dll,方便其他exe快速引入,

拿串口端來說,本質就是1.監控串口發來的訊息,然后轉發出去,2.把其他端發來的訊息推送到串口,

拿tcp端來說,本質就是1.監控tcp端發來的訊息,然后轉發出去,2.把其他端發來的訊息轉發給tcp,

默認實作了串口、tcp服務端、tcp客戶端、udp服務端、udp客戶端,也可以實作介面來實作讀寫文本,呼叫webservice等,只要是需要轉發訊息的都可,

抽取介面如下(所有的訊息實作端實作該介面):

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

namespace MessageSwitch
{
    ///<summary  NoteObject="Class">
    /// [功能描述:訊息轉換器介面,所有訊息用戶控制元件實作該介面,符合該介面的實作可以配置到轉接中心兩端] <para/>
    /// [創建者:zlz] <para/>
    /// [創建時間:2021年11月13日] <para/>
    ///<說明>
    ///  [說明:訊息轉換器介面,所有訊息用戶控制元件實作該介面,符合該介面的實作可以配置到轉接中心兩端]<para/>
    ///</說明>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///</summary>
    public interface IMessageSwitch
    {
        /// <summary>
        /// 得到實作型別的名字,供寫日志用
        /// </summary>
        /// <returns></returns>
        string GetTypeName();

        /// <summary>
        /// 得到配置串
        /// </summary>
        /// <returns>配置串</returns>
        string GetConfig();


        /// <summary>
        /// 設定配置,供主程式把配置設定上去
        /// </summary>
        /// <param name="confStr">配置串</param>
        /// <returns>是否成功</returns>
        bool SetConfig(string confStr);

        /// <summary>
        /// 供轉換中心設定回呼方法給訊息實作
        /// </summary>
        /// <param name="push">推送器</param>
        /// <param name="type">推送端來源</param>
        /// <param name="log">寫日志委托</param>
        /// <returns>是否成功</returns>
        bool SetPushDelegate(PushMessageToSwitch push, SwitchType type, WriteLog log);


        /// <summary>
        /// 啟動
        /// </summary>
        /// <returns>是否成功</returns>
        bool Start();

        /// <summary>
        /// 停止
        /// </summary>
        /// <returns>是否成功</returns>
        bool Stop();

        /// <summary>
        /// 提供轉換中心給改介面推送訊息
        /// </summary>
        /// <param name="msgByteArr">訊息的位元陣列</param>
        /// <returns>是否成功</returns>
        bool SendMessage(byte[] msgByteArr);

        /// <summary>
        /// 得到該物件的反射配置串,供主程式按配置加載,格式:類全名,動態庫名字(不帶dll)
        /// </summary>
        /// <returns></returns>
        string GetReflectStr();

    }
}

轉換器及委托實作轉換邏輯

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace MessageSwitch
{
    /// <summary>
    /// 交換型別,標識訊息實作所在的端
    /// </summary>
    public enum SwitchType
    {
        In,
        Out
    }

    /// <summary>
    /// 把收到的訊息推送到轉換器委托,所有訊息介面通過該委托把訊息推送到轉換中心
    /// </summary>
    /// <param name="msgByteArr">訊息</param>
    /// <param name="type">推送端來源</param>
    /// <returns>是否成功</returns>
    public delegate bool PushMessageToSwitch(byte[] msgByteArr,SwitchType type);

    /// <summary>
    /// 寫日志委托
    /// </summary>
    /// <param name="msg">訊息</param>
    public delegate void WriteLog(string msg);

    /// <summary>
    /// 添加轉換器
    /// </summary>
    /// <param name="sw"></param>
    public delegate void AddMessageSwitch(IMessageSwitch sw,SwitchType type);


    ///<summary  NoteObject="Class">
    /// [功能描述:訊息轉換器核心,實作訊息轉換] <para/>
    /// [創建者:zlz] <para/>
    /// [創建時間:2021年11月13日] <para/>
    ///<說明>
    ///  [說明:訊息轉換器核心,實作訊息轉換]<para/>
    ///</說明>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///</summary>
    public class SwitchMian
    {
        /// <summary>
        /// 輸入端介面集合
        /// </summary>
        private List<IMessageSwitch> inList = new List<IMessageSwitch>();

        /// <summary>
        /// 輸出端訊息集合
        /// </summary>
        private List<IMessageSwitch> outList = new List<IMessageSwitch>();

        /// <summary>
        /// 推送訊息委托
        /// </summary>
        private PushMessageToSwitch PushMessage;

        /// <summary>
        /// 寫日志委托
        /// </summary>
        private WriteLog log;


        /// <summary>
        /// 建構式
        /// </summary>
        public SwitchMian(WriteLog logW)
        {
            PushMessage = new PushMessageToSwitch(PushMessageToSwitchDo);
            log = logW;
        }

        /// <summary>
        /// 接收推過來的訊息
        /// </summary>
        /// <param name="msgByteArr">訊息</param>
        /// <param name="type">來源</param>
        /// <returns>是否成功</returns>
        private bool PushMessageToSwitchDo(byte[] msgByteArr, SwitchType type)
        {
            string lineStr = System.Text.Encoding.Default.GetString(msgByteArr);
            //處理不可見字符為可見字符
            lineStr = Util.DealNotSeeToSeeChar(lineStr);
            //訊息來自In就給所有Out推送
            if (type == SwitchType.In)
            {
                if (outList != null && outList.Count > 0)
                {
                    foreach (IMessageSwitch s in outList)
                    {
                        if (log != null)
                        {
                            log("輸入->輸出"+lineStr);
                        }
                        s.SendMessage(msgByteArr);
                    }
                }
            }
            //訊息來自Out就給所有In推送
            if (type == SwitchType.Out)
            {
                if (inList != null && inList.Count > 0)
                {
                    foreach (IMessageSwitch s in inList)
                    {
                        if (log != null)
                        {
                            log("輸出->輸入" + lineStr);
                        }
                        s.SendMessage(msgByteArr);
                    }
                }
            }
            return true;
        }

        

        /// <summary>
        /// 添加訊息實作到輸入端
        /// </summary>
        /// <param name="obj">訊息實作</param>
        public void AddToIn(IMessageSwitch obj)
        {
            if (log != null)
            {
                log(obj.GetTypeName()+"加入輸入端");
            }
            obj.SetPushDelegate(PushMessage, SwitchType.In,log);
            inList.Add(obj);
        }

        /// <summary>
        /// 添加訊息實作到輸出端
        /// </summary>
        /// <param name="obj">訊息實作</param>
        public void AddToOut(IMessageSwitch obj)
        {
            if (log != null)
            {
                log(obj.GetTypeName() + "加入輸出端");
            }
            obj.SetPushDelegate(PushMessage, SwitchType.Out,log);
            outList.Add(obj);
        }

        /// <summary>
        /// 得到配置
        /// </summary>
        /// <returns>配置串</returns>
        public string  GetConfig()
        {
            List<ConfDto> confList = new List<ConfDto>();
            if (inList != null && inList.Count > 0)
            {
                foreach (IMessageSwitch s in inList)
                {
                    if (log != null)
                    {
                        log("獲取:" + s.GetTypeName()+"配置");
                    }
                    ConfDto dto = new ConfDto();
                    dto.ConfStr = s.GetConfig();
                    dto.ReflectStr = s.GetReflectStr();
                    dto.Type = SwitchType.In;
                    confList.Add(dto);
                }
            }
            if (outList != null && outList.Count > 0)
            {
                foreach (IMessageSwitch s in outList)
                {
                    if (log != null)
                    {
                        log("獲取:" + s.GetTypeName() + "配置");
                    }
                    ConfDto dto = new ConfDto();
                    dto.ConfStr = s.GetConfig();
                    dto.ReflectStr = s.GetReflectStr();
                    dto.Type = SwitchType.Out;
                    confList.Add(dto);
                }
            }
            return Util.Serializer(confList.GetType(), confList);
        }

        /// <summary>
        /// 設定配置
        /// </summary>
        /// <param name="confStr">配置串</param>
        /// <param name="addSw">回呼方法</param>
        public void LoadConfig(string confStr,AddMessageSwitch addSw)
        {
            List<ConfDto> confList = Util.XmlDeserialize<List<ConfDto>>(confStr, Encoding.Default);
            if (confList != null && confList.Count > 0)
            {
                foreach (var v in confList)
                {
                    if (v.Type == SwitchType.In)
                    {
                        object obj = GetObjectByReflectStr(v.ReflectStr);
                        if (obj != null)
                        {
                            IMessageSwitch swi = obj as IMessageSwitch;
                            if (swi != null)
                            {
                                swi.SetConfig(v.ConfStr);
                                if (log != null)
                                {
                                    log("載入:" + swi.GetTypeName() + "物件到輸入端");
                                }
                                AddToIn(swi);
                                //執行回呼
                                if (addSw != null)
                                {
                                    addSw(swi, SwitchType.In);
                                }
                            }
                        }
                    }
                    if (v.Type == SwitchType.Out)
                    {
                        object obj = GetObjectByReflectStr(v.ReflectStr);
                        if (obj != null)
                        {
                            IMessageSwitch swi = obj as IMessageSwitch;
                            if (swi != null)
                            {
                                swi.SetConfig(v.ConfStr);
                                if (log != null)
                                {
                                    log("載入:" + swi.GetTypeName() + "物件到輸出端");
                                }
                                AddToOut(swi);
                                //執行回呼
                                if (addSw != null)
                                {
                                    addSw(swi, SwitchType.Out);
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 通過反射串得到物件
        /// </summary>
        /// <param name="reflectStr">反射串</param>
        /// <returns></returns>
        public object GetObjectByReflectStr(string reflectStr)
        {
            try
            {
                if (log != null)
                {
                    log("準備決議處理物件:" + reflectStr);
                }
                string[] strArr = reflectStr.Replace(" ", "").Split(',');
                if (strArr.Length < 2)
                {
                    if (log != null)
                    {
                        log("配置的處理物件錯誤,請采用類全名,動態庫名");
                    }
                }
                if ((strArr.Length) < 2)
                {
                    return null;
                }
                string path = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory,strArr[1]);
                if (!path.Contains(".dll"))
                {
                    path = path + ".dll";
                }
                Assembly assembly = Assembly.LoadFile(path);
                object obj = assembly.CreateInstance(strArr[0], false);
                if (log != null)
                {
                    log("決議處理物件:" + reflectStr + "成功");
                }
                return obj;
            }
            catch (Exception ex)
            {
                if (log != null)
                {
                    log("決議處理物件出錯:" + ex.Message);
                }
                return null;
            }
        }

        /// <summary>
        /// 開啟轉換器
        /// </summary>
        public void StartSwitch()
        {
            if (inList != null && inList.Count > 0)
            {
                foreach (IMessageSwitch s in inList)
                {
                    if (log != null)
                    {
                        log("開啟輸輸入端:" + s.GetTypeName());
                    }
                    s.Start();
                }
            }
            if (outList != null && outList.Count > 0)
            {
                foreach (IMessageSwitch s in outList)
                {
                    if (log != null)
                    {
                        log("開啟輸出端:" + s.GetTypeName());
                    }
                    s.Start();
                }
            }
        }

        /// <summary>
        /// 停止轉換器
        /// </summary>
        public void StopSwitch()
        {
            if (inList != null && inList.Count > 0)
            {
                foreach (IMessageSwitch s in inList)
                {
                    if (log != null)
                    {
                        log("停止輸輸入端:" + s.GetTypeName());
                    }
                    s.Stop();
                }
            }
            if (outList != null && outList.Count > 0)
            {
                foreach (IMessageSwitch s in outList)
                {
                    if (log != null)
                    {
                        log("停止輸出端:" + s.GetTypeName());
                    }
                    s.Stop();
                }
            }
        }
    }

    /// <summary>
    /// 配置物體
    /// </summary>
    public class ConfDto
    {
        /// <summary>
        /// 反射用的串
        /// </summary>
        public string ReflectStr
        {
            get;
            set;
        }

        /// <summary>
        /// 型別
        /// </summary>
        public SwitchType Type
        {
            get;
            set;
        }

        /// <summary>
        /// 配置串
        /// </summary>
        public string ConfStr
        {
            get;
            set;
        }
    }

}

主轉換器用戶控制元件,主轉換器界面實作
在這里插入圖片描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MessageSwitch
{
    public partial class SwitchMainUI : UserControl
    {
        /// <summary>
        /// 轉換器主物件
        /// </summary>
        private SwitchMian switchMian =null;

        /// <summary>
        /// 輸入控制元件頂部
        /// </summary>
        private int InTop = 0;

        /// <summary>
        /// 輸出控制元件頂部
        /// </summary>
        private int OutTop = 0;

        public SwitchMainUI()
        {
            InitializeComponent();
        }


        /// <summary>
        /// 添加輸入端
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAddIn_Click(object sender, EventArgs e)
        {
            object reflectObj = cmbType.SelectedValue;
            if (reflectObj == null)
            {
                MessageBox.Show("請選擇要添加的型別!", "提示");
                return;
            }
            object swiObj = switchMian.GetObjectByReflectStr(reflectObj.ToString());
            IMessageSwitch swi = swiObj as IMessageSwitch;
            UserControl swiu = swiObj as UserControl;
            swiu.Top = InTop;
            InTop += swiu.Height+10;
            tabPageIn.Controls.Add(swiu);
            switchMian.AddToIn(swi);
        }

        /// <summary>
        /// 添加輸出端
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAddOut_Click(object sender, EventArgs e)
        {
            object reflectObj = cmbType.SelectedValue;
            if (reflectObj == null)
            {
                MessageBox.Show("請選擇要添加的型別!", "提示");
                return;
            }
            object swiObj = switchMian.GetObjectByReflectStr(reflectObj.ToString());
            IMessageSwitch swi = swiObj as IMessageSwitch;
            UserControl swiu = swiObj as UserControl;
            swiu.Top = OutTop;
            OutTop += swiu.Height+10;
            tabPageOut.Controls.Add(swiu);
            switchMian.AddToOut(swi);
        }

        /// <summary>
        /// 保存配置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSaveConfig_Click(object sender, EventArgs e)
        {
            string confStr=switchMian.GetConfig();
            string path = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "SwitchMian.conf");
            Util.WriteTxt(path, confStr);
            MessageBox.Show("配置保存在SwitchMian.conf!", "提示");
        }

        /// <summary>
        /// 啟動轉換
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            switchMian.StartSwitch();
        }

        /// <summary>
        /// 停止轉換
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStop_Click(object sender, EventArgs e)
        {
            switchMian.StopSwitch();
        }

        /// <summary>
        /// 加載方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SwitchMainUI_Load(object sender, EventArgs e)
        {
            switchMian = new SwitchMian(new WriteLog(WritLogs));
            string path = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "SwitchType.conf");
            string TypeConfStr = Util.ReadTxt(path);
            if (TypeConfStr != "")
            {
                TypeConfStr = TypeConfStr.Replace("\r\n",(char)0+"");
                string[] arr = TypeConfStr.Split((char)0);
                List<CmbDto> cmbList = new List<CmbDto>();
                foreach(string s in arr)
                {
                    if (s == "")
                    {
                        continue;
                    }
                    string[] arrOne = s.Split('^');
                    if (arrOne.Length != 2)
                    {
                        MessageBox.Show("配置格式不對!格式:名稱^反射串", "提示");
                    }
                    else
                    {
                        CmbDto dto = new CmbDto();
                        dto.Name = arrOne[0];
                        dto.ReflectStr = arrOne[1];
                        cmbList.Add(dto);
                    }
                }
                cmbType.DataSource = cmbList;
                cmbType.ValueMember = "ReflectStr";
                cmbType.DisplayMember = "Name";
            }
            string pathConf = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "SwitchMian.conf");
            if(System.IO.File.Exists(pathConf))
            {
                string conf=Util.ReadTxt(pathConf);
                switchMian.LoadConfig(conf, new AddMessageSwitch(AddMessageSwitchDo));
                switchMian.StartSwitch();
            }
        }

        /// <summary>
        /// 添加轉換器
        /// </summary>
        /// <param name="sw"></param>
        public  void AddMessageSwitchDo(IMessageSwitch sw,SwitchType type)
        {
            UserControl swiu = sw as UserControl;
            if (type == SwitchType.In)
            {
                swiu.Top = InTop;
                InTop += swiu.Height + 10;
                tabPageIn.Controls.Add(swiu);
            }
            if (type == SwitchType.Out)
            {
                swiu.Top = OutTop;
                OutTop += swiu.Height + 10;
                tabPageOut.Controls.Add(swiu);
            }
        }


        /// <summary>
        /// 寫日志
        /// </summary>
        /// <param name="log"></param>
        private void WritLogs(string log)
        {
            object [] para=new object[1];
            para[0]=log;
            this.Invoke(new WriteLog(WritLogsDo), para);
        }

        /// <summary>
        /// 寫日志
        /// </summary>
        /// <param name="log"></param>
        private void WritLogsDo(string log)
        {
            txtInfo.Text += DateTime.Now.ToString("HH:mm:ss ")+ log + "\n";
        }

        /// <summary>
        /// 下拉框物體
        /// </summary>
        class CmbDto
        {
            /// <summary>
            /// 顯示名稱
            /// </summary>
            public string Name
            {
                get;
                set;
            }

            /// <summary>
            /// 反射串
            /// </summary>
            public string ReflectStr
            {
                get;
                set;
            }
        }
    }
}

串口實作示例,對接串口訊息
在這里插入圖片描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace MessageSwitch
{
    ///<summary  NoteObject="Class">
    /// [功能描述:串口實作] <para/>
    /// [創建者:zlz] <para/>
    /// [創建時間:2021年11月13日] <para/>
    ///<說明>
    ///  [說明:串口實作]<para/>
    ///</說明>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///</summary>
    public partial class UCSerialPort : UserControl, IMessageSwitch
    {
        /// <summary>
        /// 串口物件
        /// </summary>
        private SerialPort comm = new SerialPort();

        /// <summary>
        /// 推送器
        /// </summary>
        private PushMessageToSwitch pushToSwitch;

        /// <summary>
        /// 型別
        /// </summary>
        SwitchType type;

        /// <summary>
        /// 寫日志委托
        /// </summary>
        private WriteLog log;

        public UCSerialPort()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 得到型別名字
        /// </summary>
        /// <returns></returns>
        public string GetTypeName()
        {
            return "串口";
        }

        /// <summary>
        /// 得到配置
        /// </summary>
        /// <returns></returns>
        public string GetConfig()
        {
            string confStr = cmbPortName.Text + "#" + cmbBaudrate.Text + "#" + cmbDataBits.Text + "#" + cmbStopBits.Text + "#" + cmbParity.Text;
            return confStr;
        }

        /// <summary>
        /// 設定配置
        /// </summary>
        /// <param name="confStr"></param>
        /// <returns></returns>
        public bool SetConfig(string confStr)
        {
            string[] arr = confStr.Split('#');
            if (arr.Length != 5)
            {
                MessageBox.Show("串口配置格式不對!應該是#分隔的5位", "提示");
                return false;
            }
            cmbPortName.Text = arr[0];
            cmbBaudrate.Text = arr[1];
            cmbDataBits.Text = arr[2];
            cmbStopBits.Text = arr[3];
            cmbParity.Text = arr[4];
            return true;
        }

        /// <summary>
        /// 設定推送委托
        /// </summary>
        /// <param name="push">推送器</param>
        /// <param name="ptype">型別</param>
        /// <param name="plog">日志委托</param>
        /// <returns></returns>
        public bool SetPushDelegate(PushMessageToSwitch push, SwitchType ptype, WriteLog plog)
        {
            pushToSwitch = push;
            type = ptype;
            log = plog;
            return true;
        }

        /// <summary>
        /// 啟動串口
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            //根據當前串口物件,來判斷操作
            if (comm.IsOpen)
            {
                //打開時點擊,則關閉串口
                comm.Close();
            }
            //關閉時點擊,則設定好埠,波特率后打開
            comm.PortName = cmbPortName.Text;
            comm.BaudRate = int.Parse(cmbBaudrate.Text);
            comm.DataBits = int.Parse(cmbDataBits.Text);
            //停止位為列舉型別非用戶自定義 
            switch (cmbStopBits.Text)
            {
                default:
                    comm.StopBits = StopBits.None;
                    break;
                case "1":
                    comm.StopBits = StopBits.One;
                    break;
                case "2":
                    comm.StopBits = StopBits.Two;
                    break;
                case "1.5":
                    comm.StopBits = StopBits.OnePointFive;
                    break;
            }
            //校驗位同樣非用戶自定義 
            switch (cmbParity.Text)
            {
                default:
                    comm.Parity = Parity.None;
                    break;
                case "Odd":
                    comm.Parity = Parity.Odd;
                    break;
                case "Even":
                    comm.Parity = Parity.Even;
                    break;
                case "Mark":
                    comm.Parity = Parity.Mark;
                    break;
                case "Space":
                    comm.Parity = Parity.Space;
                    break;
            }
            try
            {
                comm.Open();
                if (log != null)
                {
                    log("啟動:啟動串口成功");
                    statePortName.ForeColor = Color.Blue;
                }
            }
            catch (Exception ex)
            {
                statePortName.ForeColor = Color.Red;
                //捕獲到例外資訊,創建一個新的comm物件,之前的不能用了,
                comm = new SerialPort();
                //初始化SerialPort物件
                comm.NewLine = "\r\n";
                comm.RtsEnable = true;//根據實際情況吧,
                //添加事件注冊
                comm.DataReceived += cmb_DataReceived;
                //現實體外資訊給客戶,                    
                MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 停止串口
        /// </summary>
        /// <returns></returns>
        public bool Stop()
        {
            if (comm.IsOpen)
            {
                comm.Close();
                statePortName.ForeColor = Color.Red;
                if (log != null)
                {
                    log("停止:串口已關閉");
                    statePortName.ForeColor = Color.Blue;
                }
            }
            return true;
        }

        /// <summary>
        /// 給串口發訊息
        /// </summary>
        /// <param name="msgByteArr"></param>
        /// <returns></returns>
        public bool SendMessage(byte[] msgByteArr)
        {
            //串口打開的話就轉給串口
            if (comm.IsOpen)
            {
                //轉發給串口
                comm.Write(msgByteArr, 0, msgByteArr.Count());
            }
            else
            {
                if (log != null)
                {
                    log("串口未打開,無法發送");
                    statePortName.ForeColor = Color.Blue;
                }
            }
            return true;
        }

        /// <summary>
        /// 得到反射串
        /// </summary>
        /// <returns></returns>
        public string GetReflectStr()
        {
            return "MessageSwitch.UCSerialPort,MessageSwitch.dll";
        }

        /// <summary>
        /// 加載函式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UCSerialPort_Load(object sender, EventArgs e)
        {
            //初始化下拉串口名稱串列框
            string[] ports = SerialPort.GetPortNames();
            //沒串口提示
            if (ports == null || ports.Count() == 0)
            {
                MessageBox.Show("檢測到當前運行電腦沒有串口!");
            }
            Array.Sort(ports);
            cmbPortName.Items.AddRange(ports);
            //波特率
            string[] baudrates = { "1200", "2400", "4800", "9600", "19200", "38400", "57600", "115200" };
            cmbBaudrate.Items.AddRange(baudrates);
            //資料位
            string[] databits = { "8", "7", "6", "5", "4" };
            cmbDataBits.Items.AddRange(databits);
            //停止位
            string[] stopbits = { "1", "1.5", "2" };
            cmbStopBits.Items.AddRange(stopbits);
            //校驗位
            string[] parity = { "None", "Odd", "Even", "Mark", "Speace" };
            cmbParity.Items.AddRange(parity);

            //默認值設定
            cmbPortName.SelectedIndex = cmbPortName.Items.Count > 0 ? 0 : -1;
            cmbBaudrate.SelectedIndex = cmbBaudrate.Items.IndexOf("9600");
            cmbDataBits.SelectedIndex = cmbDataBits.Items.IndexOf("8");
            cmbStopBits.SelectedIndex = cmbStopBits.Items.IndexOf("1");
            cmbParity.SelectedIndex = cmbParity.Items.IndexOf("None");
            //下拉框只可選擇不可編輯
            cmbPortName.DropDownStyle = ComboBoxStyle.DropDownList;
            cmbBaudrate.DropDownStyle = ComboBoxStyle.DropDownList;
            cmbDataBits.DropDownStyle = ComboBoxStyle.DropDownList;
            cmbStopBits.DropDownStyle = ComboBoxStyle.DropDownList;
            cmbParity.DropDownStyle = ComboBoxStyle.DropDownList;

            //初始化SerialPort物件
            comm.NewLine = "\r\n";
            //根據實際情況吧,
            comm.RtsEnable = true;
            //添加事件注冊
            comm.DataReceived += cmb_DataReceived;
        }

        /// <summary>
        /// Com口接收資料
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void cmb_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int n = comm.BytesToRead;//先記錄下來,避免某種原因,人為的原因,操作幾次之間時間長,快取不一致
            byte[] buf = new byte[n];//宣告一個臨時陣列存盤當前來的串口資料
            comm.Read(buf, 0, n);//讀取緩沖資料
            string lineStr = System.Text.Encoding.Default.GetString(buf);
            lineStr = Util.DealNotSeeToSeeChar(lineStr);
            if (pushToSwitch != null)
            {
                pushToSwitch(buf, type);
            }


        }

        /// <summary>
        /// 啟動
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            Start();
        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStop_Click(object sender, EventArgs e)
        {
            Stop();
        }
    }
}

TCP服務端實作示例,實作TCP服務端接收客戶端訊息
在這里插入圖片描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace MessageSwitch
{
    ///<summary  NoteObject="Class">
    /// [功能描述:TCP服務端實作] <para/>
    /// [創建者:zlz] <para/>
    /// [創建時間:2021年11月13日] <para/>
    ///<說明>
    ///  [說明:TCP服務端實作]<para/>
    ///</說明>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///</summary>
    public partial class UCTcpServer : UserControl, IMessageSwitch
    {
        /// <summary>
        /// 網路服務物件
        /// </summary>
        private Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        /// <summary>
        /// 是否打開
        /// </summary>
        private bool IsOpen = false;

        /// <summary>
        /// 推送器
        /// </summary>
        private PushMessageToSwitch pushToSwitch;

        /// <summary>
        /// 型別
        /// </summary>
        SwitchType type;

        /// <summary>
        /// 寫日志委托
        /// </summary>
        private WriteLog log;

        /// <summary>
        /// 網路客戶端
        /// </summary>
        public Socket mianClient = null;

        /// <summary>
        /// 建構式
        /// </summary>
        public UCTcpServer()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 得到型別名字
        /// </summary>
        /// <returns></returns>
        public string GetTypeName()
        {
            return "TCP服務端";
        }

        /// <summary>
        /// 得到配置
        /// </summary>
        /// <returns></returns>
        public string GetConfig()
        {
            string confStr = txtIp.Text + "#" + txtPort.Text;
            return confStr;
        }

        /// <summary>
        /// 設定配置
        /// </summary>
        /// <param name="confStr"></param>
        /// <returns></returns>
        public bool SetConfig(string confStr)
        {
            string[] arr = confStr.Split('#');
            if (arr.Length != 2)
            {
                MessageBox.Show("TCP配置格式不對!應該是#分隔的2位", "提示");
                return false;
            }
            txtIp.Text = arr[0];
            txtPort.Text = arr[1];
            return true;
        }

        /// <summary>
        /// 設定推送委托
        /// </summary>
        /// <param name="push">推送器</param>
        /// <param name="ptype">型別</param>
        /// <param name="plog">日志委托</param>
        /// <returns></returns>
        public bool SetPushDelegate(PushMessageToSwitch push, SwitchType ptype, WriteLog plog)
        {
            pushToSwitch = push;
            type = ptype;
            log = plog;
            return true;
        }

        /// <summary>
        /// 啟動
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            if (txtPort.Text == "")
            {
                if (log != null)
                {
                    log("啟動:沒有設定埠號");
                }
                return false;
            }
            if (txtIp.Text == "")
            {
                if (log != null)
                {
                    log("啟動:沒有設定端IP");
                }
                return false;
            }
            //先釋放
            if (socket != null)
            {
                socket.Close();
                socket.Dispose();
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IsOpen = false;
            }
            //系結IP埠
            IPAddress hostIP = IPAddress.Any;
            IPAddress.TryParse(txtIp.Text, out hostIP);
            if (Util.PortInUse(Convert.ToInt32(txtPort.Text)))
            {
                if (log != null)
                {
                    log("啟動TCP服務:當前電腦埠:" + txtPort.Text + "已經被占用");
                }
                //現實體外資訊給客戶,                    
                MessageBox.Show("當前電腦埠:" + txtPort.Text + "已經被占用", "提示", MessageBoxButtons.OK);
                return false;
            }
            IPEndPoint ep = new IPEndPoint(hostIP, Convert.ToInt32(txtPort.Text));
            socket.Bind(ep);
            try
            {
                //開始偵聽 
                socket.Listen(20);
                if (log != null)
                {
                    log("啟動TCP服務:啟動TCP服務成功");
                }
                stateIp.ForeColor = Color.Blue;
                Thread tcpThread = new Thread(new ThreadStart(TcpListenClientConnect));
                IsOpen = true;
                tcpThread.Start();
                return true;
            }
            catch (Exception ex)
            {
                IsOpen = false;
                //現實體外資訊給客戶,                    
                MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK);
                return false;
            }
        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <returns></returns>
        public bool Stop()
        {
            if (socket != null)
            {
                socket.Close();
                stateIp.ForeColor = Color.Red;
                socket.Dispose();
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IsOpen = false;
                if (log != null)
                {
                    log("停止TCP服務:TCP已釋放");
                }
            }
            return true;
        }

        /// <summary>
        /// 給tcp發送訊息
        /// </summary>
        /// <param name="msgByteArr"></param>
        /// <returns></returns>
        public bool SendMessage(byte[] msgByteArr)
        {
            //轉發給TCP
            if (mianClient != null)
            {
                mianClient.Send(msgByteArr);
                return true;
            }
            else
            {
                if (log != null)
                {
                    log("TCP無連接客戶端,無法發送,確認防火墻關閉!");
                }
                return false;
            }
        }

        /// <summary>
        /// 得到反射串
        /// </summary>
        /// <returns></returns>
        public string GetReflectStr()
        {
            return "MessageSwitch.UCTcpServer,MessageSwitch.dll";
        }

        /// <summary>
        /// 加載方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UCTcpServer_Load(object sender, EventArgs e)
        {
            txtIp.Text = Util.GetIpv4Str();
        }

        /// <summary>
        /// 監聽客戶端連接
        /// </summary>
        private void TcpListenClientConnect()
        {
            //死回圈偵聽客戶端連接
            while (true)
            {
                try
                {
                    if (IsOpen == false)
                    {
                        break;
                    }
                    //有客戶端連接過來
                    Socket oneClient = socket.Accept();
                    string clentIP = ((IPEndPoint)oneClient.RemoteEndPoint).Address.ToString();
                    string clientPort = ((IPEndPoint)oneClient.RemoteEndPoint).Port.ToString();
                    if (log != null)
                    {
                        log("客戶端:" + clentIP + ":" + clientPort + "連接了本服務");
                    }
                    //服務只接收一個客戶端
                    if (mianClient == null)
                    {
                        if (log != null)
                        {
                            log("客戶端:" + clentIP + ":" + clientPort + "作為主客戶端");
                        }
                        mianClient = oneClient;
                        Thread newThread = new Thread(ListenClientData);
                        newThread.Start();
                    }
                    else
                    {
                        if (log != null)
                        {
                            log("已有客戶端連接本服務,將斷開當前客戶端請求");
                        }
                        //有客戶端連著就不讓其他客戶端連接了
                        byte[] byteArray = System.Text.Encoding.Default.GetBytes("已有連接連上該埠了!");
                        oneClient.Send(byteArray);
                        oneClient.Close();
                    }
                }
                catch (Exception ex)
                {
                    if (log != null)
                    {
                        log("服務端偵聽例外:" + ex.Message);
                    }
                }
            }
        }


        /// <summary>
        /// 偵聽客戶端訊息
        /// </summary>
        public void ListenClientData()
        {
            byte[] bytes = new byte[83886080];
            //數量
            int datai = -1;
            try
            {
                //死回圈偵聽客戶端發來的資料
                while (true)
                {
                    if (IsOpen == false)
                    {
                        break;
                    }
                    datai = mianClient.Receive(bytes);
                    if (datai > 0)
                    {
                        if (pushToSwitch != null)
                        {
                            byte[] buf = new byte[datai];
                            Array.Copy(bytes, buf, datai);
                            pushToSwitch(buf, type);
                        }
                    }

                }
            }
            catch (System.Exception ex)
            {
                if (log != null)
                {
                    log("偵聽客戶端訊息例外:" + ex.Message);
                }
            }
            finally
            {
                if (mianClient != null)
                {
                    mianClient.Close();
                    mianClient.Dispose();
                    mianClient = null;
                }
            }
        }

        /// <summary>
        /// 啟動
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            Start();
        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStop_Click(object sender, EventArgs e)
        {
            Stop();
        }
    }
}

工具類,共用方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Net.NetworkInformation;
using System.Net;

namespace MessageSwitch
{
    ///<summary  NoteObject="Class">
    /// [功能描述:工具類] <para/>
    /// [創建者:zlz] <para/>
    /// [創建時間:2021年11月13日] <para/>
    ///<說明>
    ///  [說明:工具類]<para/>
    ///</說明>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///</summary>
    public class Util
    {
        /// <summary>
        /// 反序列化資料
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <returns></returns>
        public static T ReadLocalData<T>(string path)
        {
            if (File.Exists(path))
            {
                try
                {
                    string str = ReadTxt(path);
                    byte[] arr = Convert.FromBase64String(str);
                    str = System.Text.Encoding.Default.GetString(arr);
                    return XmlDeserialize<T>(str, Encoding.UTF8);
                }
                catch (Exception e)
                {
                    throw e;
                }
            }
            else
            {
                return default(T);
            }
        }

        /// <summary>
        /// 序列化資料
        /// </summary>
        /// <param name="data"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool WriteLocalData(object data, string path)
        {
            if (File.Exists(path))
            {
                File.Delete(path);
                try
                {
                    string str = Serializer(data.GetType(), data);
                    byte[] arr = System.Text.Encoding.Default.GetBytes(str);
                    str = Convert.ToBase64String(arr);
                    WriteTxt(path, str);
                    return true;
                }
                catch (Exception e)
                {
                    throw e;
                }
            }
            else
            {
                try
                {
                    string str = Serializer(data.GetType(), data);
                    byte[] arr = System.Text.Encoding.Default.GetBytes(str);
                    str = Convert.ToBase64String(arr);
                    WriteTxt(path, str);
                    return true;
                }
                catch (Exception e)
                {
                    throw e;
                }
            }
        }

        /// <summary>
        /// 洗掉本地資料
        /// </summary>
        /// <param name="id">Id</param>
        /// <param name="pat">路徑,不給的話有方法默認決定</param>
        /// <returns>結果</returns>
        public static bool DeleteLocalData(string id, string pat)
        {
            string path = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), id + ".aup");
            if (pat != null && pat != string.Empty)
            {
                path = Path.Combine(pat, id + ".aup");
            }
            if (File.Exists(path))
            {
                File.Delete(path);
            }
            return true;
        }

        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="type">型別</param>
        /// <param name="obj">物件</param>
        /// <returns></returns>
        public static string Serializer(Type type, object obj)
        {
            MemoryStream Stream = new MemoryStream();
            XmlSerializer xml = new XmlSerializer(type);
            try
            {
                //序列化物件
                xml.Serialize(Stream, obj);
            }
            catch (InvalidOperationException)
            {
                throw;
            }
            Stream.Position = 0;
            StreamReader sr = new StreamReader(Stream);
            string str = sr.ReadToEnd();

            sr.Dispose();
            Stream.Dispose();

            return str;
        }

        /// <summary>
        /// 從XML字串中反序列化物件
        /// </summary>
        /// <typeparam name="T">結果物件型別</typeparam>
        /// <param name="s">包含物件的XML字串</param>
        /// <param name="encoding">編碼方式</param>
        /// <returns>反序列化得到的物件</returns>
        public static T XmlDeserialize<T>(string s, Encoding encoding)
        {
            try
            {
                if (string.IsNullOrEmpty(s))
                {
                    throw new ArgumentNullException("s");
                }
                if (encoding == null)
                {
                    throw new ArgumentNullException("encoding");
                }

                XmlSerializer mySerializer = new XmlSerializer(typeof(T));
                using (MemoryStream ms = new MemoryStream(encoding.GetBytes(s)))
                {
                    using (StreamReader sr = new StreamReader(ms, encoding))
                    {
                        return (T)mySerializer.Deserialize(sr);
                    }
                }
            }
            catch (Exception ex)
            {
                return default(T);
            }
        }

        /// <summary>
        /// 讀取檔案資料
        /// </summary>
        /// <param name="path">檔案全路徑</param>
        /// <returns></returns>
        public static string ReadTxt(string path)
        {
            //檔案流
            FileStream fs = null;
            try
            {
                //創建檔案流
                fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                //創建字串讀取器
                StreamReader sr = new StreamReader(fs);
                //讀到尾
                string str = sr.ReadToEnd();
                return str;
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                }
            }
        }

        /// <summary>
        /// 寫入資料到指定檔案
        /// </summary>
        /// <param name="path">檔案全路徑</param>
        /// <param name="str">資料</param>
        /// <param name="isReplace">是否提換,默認為替換,否則為添加</param>
        /// <returns></returns>
        public  static bool WriteTxt(string path, string str)
        {
            FileStream fs = null;
            StreamWriter sw1 = null;
            try
            {
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
                //創建檔案流
                fs = new FileStream(path, FileMode.CreateNew);
                //創建字串寫入器
                sw1 = new StreamWriter(fs);
                //寫入字串
                sw1.Write(str);
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (sw1 != null)
                {
                    sw1.Close();
                }
                if (fs != null)
                {
                    fs.Close();
                }
            }
        }

        /// <summary>
        /// 處理不可見字符
        /// </summary>
        /// <param name="data">資料</param>
        /// <returns>回傳</returns>
        public static string DealNotSeeToSeeChar(string data)
        {
            for (int i = 0; i <= 31; i++)
            {
                if (i == 6)
                {
                    data = data.Replace((char)i + "", "[ACK]");
                }
                else if (i == 5)
                {
                    data = data.Replace((char)i + "", "[ENQ]");
                }
                else if (i == 4)
                {
                    data = data.Replace((char)i + "", "[EOT]");
                }
                else if (i == 3)
                {
                    data = data.Replace((char)i + "", "[ETX]");
                }
                else if (i == 2)
                {
                    data = data.Replace((char)i + "", "[STX]");
                }
                else
                {
                    data = data.Replace((char)i + "", "[" + i + "]");
                }
            }
            data.Replace((char)127 + "", "[127]");
            return data;
        }

        /// <summary>
        /// 判斷埠是否被占用
        /// </summary>
        /// <param name="port">埠</param>
        /// <returns></returns>
        public static bool PortInUse(int port)
        {
            bool inUse = false;

            IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
            IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();

            foreach (IPEndPoint endPoint in ipEndPoints)
            {
                if (endPoint.Port == port)
                {
                    inUse = true;
                    break;
                }
            }
            return inUse;
        }

        /// <summary>
        /// 獲得當前機器的ip4串
        /// </summary>
        /// <returns></returns>
        public static string GetIpv4Str()
        {
            System.Net.IPAddress[] arrIPAddresses = System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName());
            foreach (System.Net.IPAddress ip in arrIPAddresses)
            {
                if (ip.AddressFamily.Equals(System.Net.Sockets.AddressFamily.InterNetwork))
                {
                    return ip.ToString();
                }
            }
            return string.Empty;
        }
    }
}

運行效果-串口轉串口和TCP服務
在這里插入圖片描述

這樣就可以任意組合轉換器兩端的協議了,可以串口轉串口,串口轉tcp,tcp轉tcp,tcp轉tdp,串口轉udp====,而且每端可以配置多種協議,所以把這個稱為超級轉換器,分為轉換中心和轉換實作,

善于抽取共性,就能大大降低復雜度,實作靈活又強大的功能,面向介面編程的好處,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/356941.html

標籤:其他

上一篇:可靠資料傳輸原理詳細圖解

下一篇:網路技術——路由器及其配置

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more