一个不错的C# Telnet类库(改进了汉字显示乱码的问题)

C++利用libtelnet库完成客户端类封装telnet收发 需要根据返回数据调整接受规则,我连接设备服务器为一问一答,返回数据为JSON且以\n结尾。CThreadWrapper为基础线程类。 阅读详情
转: http://www.cnblogs.com/bluesky521/archive/2011/06/14/2081002.html  
//调用方法如下:
Telnet p = new Telnet("192.168.1.100", 23, 50);

if(p.Connect()==false)
{
  Console.WriteLine("连接失败");
  return;
}
//等待指定字符返回后才执行下一命令
p.WaitFor("login:");
p.Send("admin");
p.WaitFor("password:");
p.Send("123456");
p.WaitFor(">");
//Console.WriteLine(p.SessionLog);
Console.WriteLine(p.WorkingData);


改进后代码(注意标蓝色的部分):

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Threading;

namespace Lwolf
{
    public class Telnet
    {
        #region telnet的数据定义
        /// <summary>        
        /// 标志符,代表是一个TELNET 指令        
        /// </summary>        
        readonly Char IAC = Convert.ToChar(255);
        /// <summary>        
        /// 表示一方要求另一方使用,或者确认你希望另一方使用指定的选项。
        /// </summary>        
        readonly Char DO = Convert.ToChar(253);
        /// <summary>
        /// 表示一方要求另一方停止使用,或者确认你不再希望另一方使用指定的选项。       
        /// </summary>       
        readonly Char DONT = Convert.ToChar(254);
        /// <summary>
        /// 表示希望开始使用或者确认所使用的是指定的选项。
        /// </summary>
        readonly Char WILL = Convert.ToChar(251);
        /// <summary>
        /// 表示拒绝使用或者继续使用指定的选项。
        /// </summary>
        readonly Char WONT = Convert.ToChar(252);
        /// <summary>
        /// 表示后面所跟的是对需要的选项的子谈判
        /// </summary>
        readonly Char SB = Convert.ToChar(250);
        /// <summary>
        /// 子谈判参数的结束
        /// </summary>
        readonly Char SE = Convert.ToChar(240);
        const Char IS = '0';
        const Char SEND = '1';
        const Char INFO = '2';
        const Char VAR = '0';
        const Char VALUE = '1';
        const Char ESC = '2';
        const Char USERVAR = '3';
        /// <summary> 
        /// 流
        /// /// </summary>
        byte[] m_byBuff = new byte[100000];
        /// <summary>
        /// 收到的控制信息
        /// </summary>
        private ArrayList m_ListOptions = new ArrayList();
        /// <summary>
        /// 存储准备发送的信息
        /// </summary>
        string m_strResp;
        /// <summary>
        /// 一个Socket套接字
        /// </summary>
        private Socket s;
        #endregion

        private IPEndPoint iep;
        private string address;
        private int port;
        private int timeout;

        private string strWorkingData = "";     // 保存从服务器端接收到的数据
        private string strFullLog = "";
        //==== 夏春涛 扩充 20110531 ================================================            

        private string strWorkingDataX = "";
        //用于获取当前工作的数据内容

        public string WorkingData
        {
            get { return strWorkingDataX; }
        }
        //===================================================================
        public Telnet(string Address, int Port, int CommandTimeout)
        {
            address = Address;
            port = Port;
            timeout = CommandTimeout;
        }

        /// <summary>        
        /// 启动socket 进行telnet操作        
        /// </summary>       
        public bool Connect()
        {

            IPAddress import = GetIP(address);

            s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            iep = new IPEndPoint(import, port);

            try
            {
                // Try a blocking connection to the server
                s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                s.Connect(iep);

          //异步回调
                AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
                s.BeginReceive(m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, s);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>        
        /// 当接收完成后,执行的方法(供委托使用)       
        /// </summary>      
        /// <param name="ar"></param>       
        private void OnRecievedData(IAsyncResult ar)
        {
            try
            {
                //从参数中获得给的socket 对象           
                Socket sock = (Socket)ar.AsyncState;

                //EndReceive方法为结束挂起的异步读取         
                int nBytesRec = sock.EndReceive(ar);
                //如果有接收到数据的话            
                if (nBytesRec > 0)
                {
                    //声明一个字符串,用来存储解析过的字符串                
                    string m_strLine = "";
                    //遍历Socket接收到的字符                 
                    /*       
                     * 此循环用来调整linux 和 windows在换行上标记的区别       
                     * 最后将调整好的字符赋予给 m_strLine      
                     */
                    for (int i = 0; i < nBytesRec; i++)
                    {
                        Char ch = Convert.ToChar(m_byBuff[i]);
                        switch (ch)
                        {
                            case '\r':
                                m_strLine += Convert.ToString("\r\n");
                                break;
                            case '\n':
                                break;
                            default:
                                m_strLine += Convert.ToString(ch);
                                break;
                        }
                    }
                    try
                    {
                        //获得转义后的字符串的长度                  
                        int strLinelen = m_strLine.Length;
                        //如果长度为零                   
                        if (strLinelen == 0)
                        {
                            //则返回"\r\n" 即回车换行                    
                            m_strLine = Convert.ToString("\r\n");
                        }
                        //建立一个流,把接收的信息(转换后的)存进 mToProcess 中   
                        Byte[] mToProcess = new Byte[strLinelen];
                        for (int i = 0; i < strLinelen; i++)
                            mToProcess[i] = Convert.ToByte(m_strLine[i]);
                        //对接收的信息进行处理,包括对传输过来的信息的参数的存取和       
                        string mOutText = ProcessOptions(mToProcess);
                        //==== 夏春涛 扩充 20110531 ==============================================
                        mOutText = ConvertToGB2312(mOutText);
                        strWorkingDataX = mOutText;
                        //===================================================================
                        //解析命令后返回 显示信息(即除掉了控制信息)                        
                        if (mOutText != "")
                        {
                            //Console.Write(mOutText);//显示输出//夏春涛 去掉 20110531/////////////////////////
                            strWorkingData = mOutText;
                            strFullLog += mOutText;
                        }
                        //接收完数据,处理完字符串数据等一系列事物之后,开始回发数据          
                        RespondToOptions();
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("接收数据的时候出错了! " + ex.Message);
                    }
                }
                else// 如果没有接收到任何数据的话           
                {
                    // 关闭连接            
                    // 关闭socket               
                    sock.Shutdown(SocketShutdown.Both);
                    sock.Close();
                }
            }
            catch { }
        }
        /// <summary>        
        ///  发送数据的函数       
        /// </summary>        
        private void RespondToOptions()
        {
            try
            {
                //声明一个字符串,来存储 接收到的参数            
                string strOption;
                /*               
                 * 此处的控制信息参数,是之前接受到信息之后保存的              
                 * 例如 255   253   23   等等                                
                 */
                for (int i = 0; i < m_ListOptions.Count; i++)
                {
                    //获得一个控制信息参数                   
                    strOption = (string)m_ListOptions[i];
                    //根据这个参数,进行处理                   
                    ArrangeReply(strOption);
                }
                DispatchMessage(m_strResp);
                m_strResp = "";
                m_ListOptions.Clear();
            }
            catch (Exception ers)
            {
                Console.WriteLine("出错了,在回发数据的时候 " + ers.Message);

            }
        }
        /// <summary>        
        /// 解析接收的数据,生成最终用户看到的有效文字,同时将附带的参数存储起来       
        ///</summary>       
        ///<param name="m_strLineToProcess">收到的处理后的数据</param>     
        /// <returns></returns>     
        private string ProcessOptions(byte[] m_strLineToProcess)
        {
            string m_DISPLAYTEXT = "";
            string m_strTemp = "";
            string m_strOption = "";
            string m_strNormalText = "";
            bool bScanDone = false;
            int ndx = 0;
            int ldx = 0;
            char ch;
            try
            {
                //把数据从byte[] 转化成string    
                for (int i = 0; i < m_strLineToProcess.Length; i++)
                {
                    Char ss = Convert.ToChar(m_strLineToProcess[i]);
                    m_strTemp = m_strTemp + Convert.ToString(ss);
                }
                                
                //此处意义为,当没描完数据前,执行扫描      
                while (bScanDone != true)
                {
                    //获得长度                
                    int lensmk = m_strTemp.Length;
                    //之后开始分析指令,因为每条指令为255 开头,故可以用此来区分出每条指令 
                    ndx = m_strTemp.IndexOf(Convert.ToString(IAC));
                    //此处为出错判断,本无其他含义               
                    if (ndx > lensmk)
                        ndx = m_strTemp.Length;

                    //此处为,如果搜寻到IAC标记的telnet 指令,则执行以下步骤        
                    if (ndx != -1)
                    {
                        #region 如果存在IAC标志位
                        // 将 标志位IAC 的字符 赋值给最终显示文字           
                        m_DISPLAYTEXT += m_strTemp.Substring(0, ndx);
                        // 此处获得命令码              
                        ch = m_strTemp[ndx + 1];
                        //如果命令码是253(DO) 254(DONT)  521(WILL) 252(WONT) 的情况下 
                        if (ch == DO || ch == DONT || ch == WILL || ch == WONT)
                        {

                            //将以IAC 开头3个字符组成的整个命令存储起来          
                            m_strOption = m_strTemp.Substring(ndx, 3);
                            m_ListOptions.Add(m_strOption);
                            // 将 标志位IAC 的字符 赋值给最终显示文字                         
                            m_DISPLAYTEXT += m_strTemp.Substring(0, ndx);
                            //将处理过的字符串删去                          
                            string txt = m_strTemp.Substring(ndx + 3);
                            m_strTemp = txt;
                        }
                        //如果IAC后面又跟了个IAC (255)  
                        else if (ch == IAC)
                        {
                            //则显示从输入的字符串头开始,到之前的IAC 结束        
                            m_DISPLAYTEXT = m_strTemp.Substring(0, ndx);
                            //之后将处理过的字符串排除出去                  
                            m_strTemp = m_strTemp.Substring(ndx + 1);
                        }
                        //如果IAC后面跟的是SB(250)       
                        else if (ch == SB)
                        {
                            m_DISPLAYTEXT = m_strTemp.Substring(0, ndx);
                            ldx = m_strTemp.IndexOf(Convert.ToString(SE));
                            m_strOption = m_strTemp.Substring(ndx, ldx);
                            m_ListOptions.Add(m_strOption);
                            m_strTemp = m_strTemp.Substring(ldx);
                        }
                        #endregion
                    }
                    //若字符串里已经没有IAC标志位了  
                    else
                    {

                        //显示信息累加上m_strTemp存储的字段      
                        m_DISPLAYTEXT = m_DISPLAYTEXT + m_strTemp;
                        bScanDone = true;
                    }
                }
                //输出人看到的信息    
                m_strNormalText = m_DISPLAYTEXT;
            }
            catch (Exception eP)
            {
                throw new Exception("解析传入的字符串错误:" + eP.Message);
            } 
            
            return m_strNormalText;
        }
        /// <summary>      
        /// 获得IP地址      
        /// </summary>       
        /// <param name="import"></param>    
        /// <returns></returns>   
        private static IPAddress GetIP(string import)
        {
            IPHostEntry IPHost = Dns.GetHostEntry(import);
            return IPHost.AddressList[0];
        }

        #region magic Function
        //解析传过来的参数,生成回发的数据到m_strResp   
        private void ArrangeReply(string strOption)
        {
            try
            {
                Char Verb;
                Char Option;
                Char Modifier;
                Char ch;
                bool bDefined = false;
                //排错选项,无啥意义              
                if (strOption.Length < 3) return;
                //获得命令码               
                Verb = strOption[1];
                //获得选项码             
                Option = strOption[2];
                //如果选项码为 回显(1) 或者是抑制继续进行(3)
                if (Option == 1 || Option == 3)
                {
                    bDefined = true;
                }
                // 设置回发消息,首先为标志位255         
                m_strResp += IAC;
                //如果选项码为 回显(1) 或者是抑制继续进行(3) ==true   
                if (bDefined == true)
                {
                    #region 继续判断
                    //如果命令码为253 (DO)             
                    if (Verb == DO)
                    {
                        //我设置我应答的命令码为 251(WILL) 即为支持 回显或抑制继续进行     
                        ch = WILL;
                        m_strResp += ch;
                        m_strResp += Option;
                    }
                    //如果命令码为 254(DONT)     
                    if (Verb == DONT)
                    {
                        //我设置我应答的命令码为 252(WONT) 即为我也会"拒绝启动" 回显或抑制继续进行
                        ch = WONT;
                        m_strResp += ch;
                        m_strResp += Option;
                    }
                    //如果命令码为251(WILL)   
                    if (Verb == WILL)
                    {
                        //我设置我应答的命令码为 253(DO) 即为我认可你使用回显或抑制继续进行 
                        ch = DO;
                        m_strResp += ch;
                        m_strResp += Option;
                        //break;               
                    }
                    //如果接受到的命令码为251(WONT)         
                    if (Verb == WONT)
                    {
                        //应答  我也拒绝选项请求回显或抑制继续进行       
                        ch = DONT;
                        m_strResp += ch;
                        m_strResp += Option;
                        //break;            
                    }
                    //如果接受到250(sb,标志子选项开始)            
                    if (Verb == SB)
                    {
                        /*                  
                         * 因为启动了子标志位,命令长度扩展到了4字节,                    
                         * 取最后一个标志字节为选项码                     
                         * 如果这个选项码字节为1(send)                    
                         * 则回发为 250(SB子选项开始) + 获取的第二个字节 + 0(is) + 255(标志位IAC) + 240(SE子选项结束)               
                         */
                        Modifier = strOption[3];
                        if (Modifier == SEND)
                        {
                            ch = SB;
                            m_strResp += ch;
                            m_strResp += Option;
                            m_strResp += IS;
                            m_strResp += IAC;
                            m_strResp += SE;
                        }
                    }
                    #endregion
                }
                else //如果选项码不是1 或者3 
                {
                    #region 底下一系列代表,无论你发那种请求,我都不干
                    if (Verb == DO)
                    {
                        ch = WONT;
                        m_strResp += ch;
                        m_strResp += Option;
                    }
                    if (Verb == DONT)
                    {
                        ch = WONT;
                        m_strResp += ch;
                        m_strResp += Option;
                    }
                    if (Verb == WILL)
                    {
                        ch = DONT;
                        m_strResp += ch;
                        m_strResp += Option;
                    }
                    if (Verb == WONT)
                    {
                        ch = DONT;
                        m_strResp += ch;
                        m_strResp += Option;
                    }
                    #endregion
                }
            }
            catch (Exception eeeee)
            {
                throw new Exception("解析参数时出错:" + eeeee.Message);
            }
        }
        /// <summary>     
        /// 将信息转化成charp[] 流的形式,使用socket 进行发出   
        /// 发出结束之后,使用一个匿名委托,进行接收,  
        /// 之后这个委托里,又有个委托,意思是接受完了之后执行OnRecieveData 方法 
        ///       
        /// </summary>       
        /// <param name="strText"></param>  
        void DispatchMessage(string strText)
        {
            try
            {
                //申请一个与字符串相当长度的char流      
                Byte[] smk = new Byte[strText.Length];
                for (int i = 0; i < strText.Length; i++)
                {
                    //解析字符串,将其存储到char流中去   
                    Byte ss = Convert.ToByte(strText[i]);
                    smk[i] = ss;
                }
                //发送char流,之后发送完毕后执行委托中的方法(此处为匿名委托)    
                IAsyncResult ar2 = s.BeginSend(smk, 0, smk.Length, SocketFlags.None, delegate(IAsyncResult ar)
                {
                    //当执行完"发送数据" 这个动作后                  
                    // 获取Socket对象,对象从beginsend 中的最后个参数上获得          
                    Socket sock1 = (Socket)ar.AsyncState;
                    if (sock1.Connected)//如果连接还是有效                    
                    {
                        //这里建立一个委托      
                        AsyncCallback recieveData = new AsyncCallback(OnRecievedData);

                        sock1.BeginReceive(m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, sock1);
                      
                    }
                }, s);

                s.EndSend(ar2);
            }
            catch (Exception ers)
            {
                Console.WriteLine("出错了,在回发数据的时候:" + ers.Message);
            }
        }

        /// <summary>
        /// 等待指定的字符串返回
        /// </summary>
        /// <param name="DataToWaitFor">等待的字符串</param>
        /// <returns>返回0</returns>
        public int WaitFor(string DataToWaitFor)
        {
            long lngStart = DateTime.Now.AddSeconds(this.timeout).Ticks;
            long lngCurTime = 0;

            while (strWorkingData.ToLower().IndexOf(DataToWaitFor.ToLower()) == -1)
            {
                lngCurTime = DateTime.Now.Ticks;
                if (lngCurTime > lngStart)
                {
                    throw new Exception("Timed Out waiting for : " + DataToWaitFor);
                }
                Thread.Sleep(1);
            }
            strWorkingData = "";
            return 0;
        }

        public void Send(string message)
        {
            DispatchMessage(message);
            //因为每发送一行都没有发送回车,故在此处补上         
            DispatchMessage("\r\n");
        }
        #endregion

        /// <summary>
        /// 取完整日志
        /// </summary>
        public string SessionLog
        {
            get
            {
                return strFullLog;
            }
        }

        //======================================================================================
        /// <summary>
        /// 字符串编码转换,解决汉字显示乱码问题。

        /// 原始字符串中的汉字存储的是汉字内码,此代码实质是将汉字内码转换为GB2312编码。(夏春涛20110531)
        /// </summary>
        /// <param name="str_origin">需要转换的字符串</param>
        /// <returns>转换后的字符串</returns>
        private string ConvertToGB2312(string str_origin)
        {
            char[] chars = str_origin.ToCharArray();
            byte[] bytes = new byte[chars.Length];
            for (int i = 0; i < chars.Length; i++)
            {
                int c = (int)chars[i];
                bytes[i] = (byte)c;
            }
            Encoding Encoding_GB2312 = Encoding.GetEncoding("GB2312");
            string str_converted = Encoding_GB2312.GetString(bytes);
            return str_converted;
        }
        //======================================================================================
    }
}

 


 

Brother机床数据采集实战:TCP直连、FTP监控与Web抓取三种方案详解 在工业自动化与MES系统集成中,机床数据采集是实现设备联网与OEE统计的基础环节。其核心原理是通过TCP/IP、FTP或HTTP等通用网络协议,与数控机床建立通信并解析状态数据。技术价值在于打通IT与OT层,实现生产过程的透明化与实时监控。典型应用场景包括车间设备联网、刀具寿命管理及生产报表自动生成。针对Brother机床协议封闭、接口多样的特点,本文深入拆解了TCP直连、FTP文件监控及Web端抓取三种工程实践方案,涵盖从协议逆向到C#代码实现的完整路径,为上位机开发者提供可复用的采集思路。 阅读详情

相关推荐

HS6621低功耗蓝牙芯片烧录调试全攻略:从硬件连接到协议栈问题排查

嵌入式开发中,烧录与调试是连接代码与硬件实体的关键桥梁,尤其对于低功耗蓝牙芯片这类对功耗敏感的应用场景。其核心原理是通过SWD或JTAG等调试接口,与芯片内部的调试模块通信,实现对程序的控制与状态监控。这一技术的价值在于,它不仅是功能验证的起点,更是解决复杂问题的“眼睛”,能够精准定位内存越界、中断异常、低功耗唤醒失败等棘手问题。在物联网、可穿戴设备等实际应用场景中,高效的烧录调试流程能大幅缩短开发周期。本文以昂瑞威HS6621芯片为例,深入解析其**SWD调试接口**的配置要点,并针对**低功耗模式**下

weixin_30363509的博客 422

C# 实现telnet

调用方法如下:             Telnet p = new Telnet("192.168.1.100", 23, 50);             if(p.Connect()==false)     { Console.WriteLine("连接失败"); return;     }     //等待指定字符返回后才执行下一命令             p.W

Criss@陈磊 1万+

MobaXterm完整教程:从下载安装到SSH连接与文件传输实战

在远程服务器管理与运维工作中,终端工具是IT工程师日常使用频率最高的软件之一。SSH协议作为安全远程连接的标准,结合SFTP文件传输能力,构成了高效运维的基础。传统方案往往需要同时安装多个工具来满足连接、传文件、转发图形界面等需求,操作割裂且效率偏低。MobaXterm作为一款集SSH、SFTP、远程桌面、X11转发和众多网络工具于一体的终端软件,凭借其便携化设计、会话管理和图形化文件拖拽传输,成为Windows用户管理Linux服务器的热门选择。从基础概念出发,理解SSH会话建立、密钥认证和SFTP传输原

weixin_30235225的博客 258

[转]C# Telnet

一个不错的C# Telnet类库(改进了汉字显示乱码的问题) 转自:http://www.cnblogs.com/bluesky521/archive/2011/06/14/2081002.html 园友e-shizhan给出了一个不错的C# Telnet类库,但存在汉字显示乱码的问题,本人做了改进,希望对大家有用。 原文:http://www.cnblogs.com/eshizhan/a...

weixin_30437337的博客 396

LabVIEW连接MySQL全流程:UDL配置、ODBC驱动与数据库读写实战

在测控与数据采集场景中,LabVIEW负责采集控制,MySQL承担数据存储,两者通过ADO与ODBC驱动完成通信。UDL文件作为可视化连接配置工具,本质是保存连接字符串并支持测试连接,能显著降低配置门槛。理解连接链路中Provider、驱动位数、认证方式等基础原理,是稳定读写MySQL的前提。面向生产线数据采集、实验室自动化等高频写入场景,合理使用UDL配置、批量插入与连接管理策略,可有效避免数据丢失和性能瓶颈。本文从环境安装、UDL创建到LabVIEW编程,梳理一套可落地的连接与排错方案。

weixin_33889665的博客 614

工业仿真与Unity3D实时可视化集成:构建数字孪生的数据桥接实战

在工业数字化转型中,实时3D可视化是连接复杂仿真数据与直观认知的关键技术。其核心原理在于通过高效的数据通信协议,将仿真计算产生的时序状态与事件数据,同步驱动3D场景中的实体对象,实现虚实状态的精准映射。这项技术的核心价值在于打通了设计、仿真与运维的壁垒,为虚拟调试、操作培训和预测性维护等应用场景提供了沉浸式的交互界面。本文聚焦于工业仿真平台与Unity3D引擎的深度集成,详细阐述了以“数据桥接”为核心的松耦合架构设计,并深入探讨了模型优化、网络通信选型及数据驱动同步等工程实践,为构建高性能工业数字孪生应用提

weixin_30530939的博客 439

QTP自动化测试之使用外部.Net DLL实现与Telnet的交互

QTP自动化测试之使用外部.Net DLL实现与Telnet的交互 发布于:2012-11-22 21:57:18来自【群】QTP                     编辑 希望公司喜欢使用QTP进行自动化测试的同事一起探讨和交流,这是一款强大的工具,我不希望像使用按键精灵那样的使用它。QTP自动化测试跟开发一样,有着一套完整的流程和体系,那么我们就从需求开始说起。

chenfeng086的专栏 913

使用C/C++调用Telnet的方法和示例代码

在C/C++中,我们可以使用库函数和系统调用来实现Telnet客户端的功能。下面是一个详细的示例,展示了如何使用C/C++调用Telnet。请注意,实际使用中可能需要根据具体的Telnet服务器和命令进行适当的调整。此示例仅用于说明如何使用C/C++调用Telnet。希望这个示例能帮助你理解如何在C/C++中调用Telnet。如果你有任何问题,请随时提问。函数发送Telnet命令并接收响应。最后,我们关闭套接字并退出程序。函数连接到Telnet服务器,然后使用。在上面的示例代码中,我们首先使用。

TechWhizZ的博客 954

C#连接MySQL实战指南:从MySql.Data.dll到CRUD与性能优化

在日常开发中,数据库是应用数据存储的基石,而如何高效、安全地实现数据交互始终是开发者关注的核心。参数化查询是抵御SQL注入的重要防线,连接池则在大并发下显著提升性能。掌握这些基础原理,能够帮助开发者在构建桌面应用、上位机或内部工具时少走弯路。C#作为主流语言,连接MySQL最直接的方式便是使用官方提供的MySql.Data.dll驱动,它基于ADO.NET架构,通过简洁的连接字符串即可建立会话,并支持标准的增删改查操作。从环境搭建、dll版本适配,到事务处理、异步调用及批量优化,本文梳理了实际工程中的完整路

weixin_33896726的博客 302

C#实现MQTT客户端与服务端:基于MQTTnet的完整工程实践

MQTT是一种基于发布/订阅模式的轻量级消息传输协议,广泛应用于物联网、嵌入式设备及上位机通信场景。其核心原理是通过Broker中转消息,以Topic为路由标识,配合QoS等级实现不同可靠性的消息投递。理解透这套机制,对实际开发有直接价值。尤其在设备接入和调试过程中,一个本地自研Broker加功能完备的客户端工具,能显著提升联调效率。本文围绕C#语言与MQTTnet库,完整展示了如何构建MQTT客户端和服务端,涵盖连接配置、发布订阅、遗嘱消息、持久会话、断线重连等关键细节,并给出了常见问题排查与性能优化思路

weixin_34314962的博客 368

半导体设备通信核心:SECS/GEM协议栈与HSMS实现深度解析

半导体制造中,设备与MES系统的稳定通信是产线连续运行的关键,而SECS/GEM协议正是解决设备接口碎片化的行业标准。它通过E37(HSMS)建立基于TCP/IP的高速传输通道,配合E5(SECS-II)完成消息的编解码,同时以E30(GEM)定义设备状态与行为模型。理解这套协议栈的原理,有助于工程师掌握设备与Host之间连接建立、心跳保活、消息帧封装及数据交互的完整链路。在实际应用中,无论是配方下发、过程数据采集还是报警上报,都依赖这套标准的可靠性。本文基于JngHightSpeedSecs开源实现,拆解

weixin_33912453的博客 543

C#上位机.NET开发从入门到实战:核心知识、项目案例与高频踩坑指南

上位机开发是工业自动化与设备互联的关键技术,常与C#和.NET绑定。C#凭借丰富的类库、成熟的WinForms/WPF框架以及硬件SDK的广泛支持,成为串口通信、Socket通信和多线程UI刷新的首选语言。其底层原理包括Windows消息循环、数据组帧、线程切换与协议解析,掌握这些知识能显著提升设备监控、产线数据采集与绑定系统的稳定性。在实际应用中,从串口扫码枪到TCP仪表,从Modbus到SQLite,C#上位机均需解决粘包、超时、跨线程等工程挑战。本文结合实战案例,系统梳理技术选型、核心知识点、完整项目

weixin_34357928的博客 293

c#实现telnet功能

这是一个可以实现telnet的类库,调用里面的方法就可以返回一个服务器是否开了某个端口

OPC软件访问PLC数据实战:从配置到稳定运行的完整指南

在工业自动化领域,PLC数据采集是实现设备监控与MES集成的关键。OPC作为行业标准接口,通过统一通信规范解决多品牌PLC数据交换难题。其核心原理是服务端将PLC私有协议转换为标准OPC协议,客户端订阅标签实现数据消费。合理配置刷新频率、超时时间与死区值,可显著提升通信稳定性与实时性。典型应用包括产线状态监控、能耗管理与质量追溯。本文以Classic OPC为例,详解PLC通信配置、OPC服务端搭建及客户端读取验证,并分享DCOM配置、数据异常排查等实战避坑经验,助你打通从PLC到上位机的数据通道。

weixin_34277853的博客 459

C++实现telnet代码

C++实现telnet代码,用C++写的telnet

C# telnet

C# telnet,

自动化应届生入行指南:PLC编程与现场调试经验分享

PLC编程是工业自动化控制的核心技术,通过循环扫描机制实现逻辑控制与模拟量处理。掌握PLC编程不仅能提升设备控制效率,还能实现从单机到SCADA系统的数据交互与通信。在汽车制造、电子生产、水处理等场景中,PLC与Modbus、OPC UA等通信协议结合,支撑着产线自动化与故障排查。对于自动化应届生而言,理解扫描周期、模拟量转换和现场调试思维,是跨越学校与现场鸿沟的关键。本文围绕PLC编程入门、通信配置及职业成长,分享90条实战经验,帮助新手快速适应工业现场。

weixin_34414196的博客 376

开源Granados介绍c# ssh

Granados是一个基于.NET的SSH客户端库。它有以下特点: 1.Granados是一个C#的开源项目。 2.同时支持SSH1和SSH2。 3.Granados实现了AES, Blowfish, TripleDES, RSA, DSA等加密验证算法。 4.实现TCP协议连接。

上一篇: C#Socket实现telnet功能
下一篇: 如何:创建和终止线程(C# 编程指南)
cg_program
博客等级 码龄19年 245粉丝 147原创
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值