C# Telnet 类库代码,谨献给还在寻找C# Telnet类库的兄弟

C# Telnet 类库代码,谨献给还在寻找C# Telnet类库的兄弟,第1张

概述C# Telnet 类库代码 今天给笔记本装了固态,速度提升很明显,很高兴,发个微博留作纪念。 自学的C#,干网络的,想弄个工具方便日常工作,想自己实现批量 *** 作的工具。 想起来很简单做起来很费劲。网上一顿乱查。 这里感谢“Telnet 非常实用的类库 - 王小壮的博客 - CSDN博客” https://blog.csdn.net/weixin_42183571/article/details/8 @H_502_2@ C# Telnet 类库代码 今天给笔记本装了固态,速度提升很明显,很高兴,发个微博留作纪念。 自学的C#,干网络的,想弄个工具方便日常工作,想自己实现批量 *** 作的工具。 想起来很简单做起来很费劲。网上一顿乱查。 这里感谢“Telnet 非常实用的类库 - 王小壮的博客 - CSDN博客” https://blog.csdn.net/weixin_42183571/article/details/80783268

这个文章给了我方向,代码看了N遍,有了很多启发。
那里面的异步没看懂,当时不懂异步,看着和天数一样。。。。
什么协议都是有协商的过程:
telnet协商代码 取自 王小壮 ,有一小点的修改。

多了不BB,上代码。

using System;using System.Collections.Generic;using System.linq;using System.Text;using System.Threading.Tasks;using System.Collections;using System.IO;using System.Net;using System.Net.sockets;using System.Threading;namespace  项目名字{        public  class Telnet        {    #region // 协商的命令码直接复制    // private byte[] receivebytes = new byte[1024]; //接受    Readonly Char IAC = Convert.tochar(255);    Readonly Char DO = Convert.tochar(253);    Readonly Char DONT = Convert.tochar(254);    Readonly Char WILL = Convert.tochar(251);    Readonly Char WONT = Convert.tochar(252);    Readonly Char SB = Convert.tochar(250);    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‘;    private ArrayList m_ListOptions = new ArrayList();    enum Verbs { WILL = 251,WONT = 252,DO = 253,DONT = 254,IAC = 255 }    enum Options { RD = 1,SGA = 3 }    private Socket sock = null;  // 定义全局变量,方便调用            //定义事件    private static ManualresetEvent connectDone = new ManualresetEvent(false);    private static ManualresetEvent receiveDone = new ManualresetEvent(false);    private static ManualresetEvent sendDone = new ManualresetEvent(false);    // private static ManualresetEvent waitDone = new ManualresetEvent(false);    // private string str_data = "";// 接受到的数据    private StringBuilder str_data = new StringBuilder();// 所有收到的数据    private StringBuilder Str_Temp = new StringBuilder();//单个命令的执行结果,不完整实际没有用    public bool Connected //连接状态    {        get        {            if (sock != null)            {                return sock.Connected;            }            else            {                return false;            }        }        // get return = sock.Connected;        // set;     }    public string Recdata //取得执行的log    {        //get        //{    return str_data;        //}        get        {            return str_data.ToString();        }    }    public string TempData //取得每个命令执行的log,有问题,没有用    {        //get        //{    return str_data;        //}        get        {            return Str_Temp.ToString();        }    }    #endregion    public Telnet(string IP)        : this(IP,23) { } //构造函数链    public Telnet(string IP,int port)// 工作主函数    {        //IPAddress ipAddress = IPAddress.Parse("192.168.56.2");        IPAddress ipAddress = IPAddress.Parse(IP);        IPEndPoint remoteEP = new IPEndPoint(ipAddress,port);        sock = new Socket(ipAddress.AddressFamily,SocketType.Stream,ProtocolType.Tcp);        Console.Writeline("connectDone.Rese : 设置为无信号开始连接");        connectDone.reset();        sock.BeginConnect(remoteEP,new AsyncCallback(ConnectCallback),sock);// 异步连接        connectDone.WaitOne(10000,false);//异步阻断,连接成功就进入下异步,加入连接超时间10S,        if (!connectDone.WaitOne(10000,false))        {            sock.Close();//连接失败,超时退出;               Console.Writeline("连接失败,超时退出");        }        else   //  如果连接成功,开始接受数据。        {            //开始异步接受的线程            Thread threadread = new Thread(new ThreadStart(Receive));            threadread.Start();        }    }    /// <summary>    /// 用户名密码默认回显为“:”    /// </summary>    /// <param name="IP"></param>    /// <param name="port"></param>    /// <param name="username"></param>    /// <param name="passwd"></param>    public Telnet(string IP,int port,string username,string passwd)// 工作主函数       :this(IP,port,username,passwd,":",":") //这里的两个冒号是登录连接设备的回显,    {    }    public Telnet(string IP,string passwd,string usernamewait,string passwDWait)// 工作主函数    {        //IPAddress ipAddress = IPAddress.Parse("192.168.56.2");        IPAddress ipAddress = IPAddress.Parse(IP);        IPEndPoint remoteEP = new IPEndPoint(ipAddress,false);        if (!connectDone.WaitOne(10000,false))        {            sock.Close();//连接失败,超时退出;               Console.Writeline("连接失败,超时退出");        }        else   //  如果连接成功,开始接受数据。        {            //开始异步接受的线程            Thread threadread = new Thread(new ThreadStart(Receive));            threadread.Start();            Send(usernamewait,username + "\r"); //@R_403_6422@配置,可以手动            Send(passwDWait,passwd + "\r");        }    }    public Telnet(string IP,int timeout)// 工作主函数    {        //IPAddress ipAddress = IPAddress.Parse("192.168.56.2");        IPAddress ipAddress = IPAddress.Parse(IP);        IPEndPoint remoteEP = new IPEndPoint(ipAddress,sock);// 异步连接        connectDone.WaitOne(timeout*1000,false);        if (!connectDone.WaitOne(timeout * 1000,false))        {            sock.Close();//连接失败,超时退出;               Console.Writeline("连接失败,超时退出");        }        else   //  如果连接成功,开始接受数据。        {            //开始异步接受的线程            Thread threadread = new Thread(new ThreadStart(Receive));            threadread.Start();        }    }    /// <summary>    /// 异步连接,异步回调    /// </summary>    /// <param name="ar"></param>    private voID ConnectCallback(IAsyncResult ar)    {        try        {            // RetrIEve the socket from the state object.              Socket clIEnt = (Socket)ar.AsyncState;            // Complete the connection.              clIEnt.EndConnect(ar);            //Console.Writeline("Socket connected to {0}",//    clIEnt.RemoteEndPoint.ToString());            //// Signal that the connection has been made.              Console.Writeline(" connectDone.Set:设置为有信号");             connectDone.Set();  // 这里是把连接的事件作为 有信号,主函数中的阻断会继续执行,否则10s超时了        }        catch (Exception e)        {            Console.Writeline("异步连接:" + e.ToString());        }    }            //这里是接受数据的方法    private voID Receive()    {        try        {          //  receiveDone.reset();                        //接受没有用阻断,这里用的是循环接受,是在回调中实现            // Create the state object.                              // 这里是查了msdn文档,有这个,主要进是传递 这个辅助类中主要是传递 socke 与 state.buffer            StateObject state = new StateObject();             state.workSocket = sock;            // Begin receiving the data from the remote device.              sock.BeginReceive(state.buffer,StateObject.BufferSize,new AsyncCallback(ReceiveCallback),state);          //  receiveDone.WaitOne(10000,false);            //string ddd = string.Empty;        }        catch (Exception e)        {            Console.Writeline(e.ToString());        }    }            //接受数据异步回调    private voID ReceiveCallback(IAsyncResult ar)    {        try        {            StateObject state = (StateObject)ar.AsyncState;            Socket clIEnt = state.workSocket;            //取得 sock 其实没必要,因为socket 是全局的变量            int bytesRead = clIEnt.EndReceive(ar);            if (bytesRead > 0)            {                            ////创建一个与接受 数据大小一致的 byte[]                                         Byte[] mtoprocess = new Byte[bytesRead];                  Array.copy(state.buffer,mtoprocess,bytesRead);//数组复制                Str_Temp = ProcessOptions(mtoprocess);//清洗掉命令码,取得回显的实际数据                                                      //  Console.Writeline("*********************************************");                Console.Write(Str_Temp);//回显本次的数据                                        // Console.Writeline("*********************************************");                                        // response = mOutText;                str_data.Append(Str_Temp);  //所有的数据,把每次的接受的数据添加到 str_data.用于后期保存log                string temps = str_data.ToString();//这里是测试每次取得数据的断点,懒得删                clIEnt.BeginReceive(state.buffer,state);                //下面进是循环取得数据的关键,每次接受完数据,又开始新的接受数据。            }            else            {                //这里是接受数据为0,正常异步接受到的数据为0时应该没有数据阻断状态,不会到这个地方。                 Console.Writeline("接受数据小于0:" + "发生异常");                clIEnt.Close();//关闭连接            }        }        catch (Exception e)        {            Console.Writeline("接受数据异常" + e.ToString());//这里是抓取异常的代码。一般telnet结束时,异步还处理阻断状态,有时会发送,没啥用。        }    }            // 发送命令的方法,这里的data 是没有 \r 回车的,    public voID Send(String data)    {        try        {            byte[] byteData = EnCoding.ASCII.GetBytes(data);            //异步发送                                            sock.BeginSend(byteData,byteData.Length,new AsyncCallback(SendCallback),sock);                                    //异步阻断,发送完成后继续执行,未完成进一只阻断,可以加超时时间   sendDone.WaitOne(10000,false);                                    sendDone.WaitOne();        }        catch        {            Console.Writeline("出现异常:{0}",data + "\r\n");        }        finally        {            //clIEnt.Shutdown(SocketShutdown);        }    }    public voID Send(char data)    {        char[] char_data = { data };        try        {            byte[] byteData = EnCoding.ASCII.GetBytes(char_data);            sock.BeginSend(byteData,sock);            sendDone.WaitOne();        }        catch        {            Console.Writeline("出现异常:{0}",data + "\r\n");        }        finally        {            //clIEnt.Shutdown(SocketShutdown);        }    }    public voID Send(char[] data)    {        try        {            byte[] byteData = EnCoding.ASCII.GetBytes(data);            sock.BeginSend(byteData,data + "\r\n");        }        finally        {            //clIEnt.Shutdown(SocketShutdown);        }    }    public voID Send(byte[] byteData)    {        try        {            //byte[] byteData = EnCoding.ASCII.GetBytes(data);            sock.BeginSend(byteData,sock);            sendDone.WaitOne();        }        catch        {            Console.Writeline("发送出现异常bytedata:{0}",byteData.ToString() + "\r\n");        }        finally        {            //clIEnt.Shutdown(SocketShutdown);        }    }    /// <summary>    /// 执行命令的方法,判断回显字符,执行命令    /// </summary>    /// <param name="expect">回显字符串判断</param>    /// <param name="command">判定成功执行的命令</param>    /// <param name="delay">执行命令的延迟</param>    public voID Send(string expect,string command,int delay_time)    {        // string local_data = string.Empty ;        int i = 0;        while (true)        {        //这里主要是判断 str_data 中的数据,接受的数据会持续写入到 这个中,接受可能有延迟,加循环判断,            if (str_data.ToString().TrimEnd().EndsWith(expect))            {                Thread.Sleep(delay_time);//执行命令的延迟                Send(command);                break;            }            else            {// 增加命令执行代码判断失败的惩罚值,8次后,当前接受的数据中还没有出现判断的字符串,socket关闭                i++;            }            Thread.Sleep(1000);//  如果当前的接受数据中没有判断的字符出现,等待1s后再次判断            if(i==8)            {                //Console.Writeline("命令执行错误,错误命令" + command + "命令执行结果:");// + str_data.ToString());                //Console.Writeline();                // Console.Writeline("命令执行错误,错误命令"+ command+"命令执行结果:" +str_data.ToString());               // str_data.Append("异常终结");                sock.Close ();                break;            }            //    }        }    }    /// <summary>    /// 执行命令的方法,默认延迟500ms。    /// </summary>    /// <param name="expect">回显字符串判断</param>    /// <param name="command">判定成功执行的命令</param>    public voID Send(string expect,string command)    {        Send(expect,command,100);    }    private static voID SendCallback(IAsyncResult ar)    {//异步发送数据        try        {            Socket clIEnt = (Socket)ar.AsyncState;            int bytesSent = clIEnt.EndSend(ar);            sendDone.Set();        }        catch (Exception e)        {            Console.Writeline(e.ToString());        }    }    /// <summary>    /// 清洗命令码。telnet的核心代码    /// </summary>    /// <param name="resbyte"></param>    /// <returns></returns>    private StringBuilder ProcessOptions(byte[] resbyte)    {//网络所得        string m_disPLAYTEXT = "";        string m_strTemp = "";        //string m_strOption = "";        //string m_strnormalText = "";        StringBuilder m_strnormalText = new StringBuilder();        bool bScanDone = false;        int ndx = 0;        int ldx = 0;        char ch,canshu;        try        {            //把数据从byte[] 转化成string            for (int i = 0; i < resbyte.Length; i++)            {                Char ss = Convert.tochar(resbyte[i]);                m_strTemp = m_strTemp + Convert.ToString(ss);            }            //此处意义为,当没描完数据前,执行扫描            while (bScanDone != true)            {                //获得长度                int lensmk = m_strTemp.Length;                //之后开始分析指令,因为每条指令为255 开头,故可以用此来区分出每条指令                ndx = m_strTemp.IndexOf(Convert.ToString(IAC));//首次出现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];//获取命令码                    canshu = m_strTemp[ndx + 2];//获取命令码                    //如果命令码是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;                        telnetproceess(ch,canshu);                    }                    //如果IAC后面又跟了个IAC (255)                    else if (ch == IAC)                    {                        //则显示从输入的字符串头开始,到之前的IAC 结束                        //m_disPLAYTEXT += m_strTemp.Substring(0,ndx);                        //之后将处理过的字符串排除出去                        m_strTemp = m_strTemp.Substring(ndx + 1);                        string xxc = m_strTemp;                    }                    //如果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 + 1);                        telnetproceess(ch,canshu);                    }                    #endregion                }                //若字符串里已经没有IAC标志位了                else                {                    //显示信息累加上m_strTemp存储的字段                    m_disPLAYTEXT = m_disPLAYTEXT + m_strTemp;                    bScanDone = true;                }            }            //输出人看到的信息            m_strnormalText.Append(m_disPLAYTEXT);        }        catch (Exception eP)        {            throw new Exception("解析传入的字符串错误:" + eP.Message);        }        return m_strnormalText;    }            //异步委托调用,这里是协商代码,测试很多设备 占时没发现什么问题    private voID telnetproceess(char ch,char canshu)    {        //如果命令码是253(DO) 254(DONT)  251(WILL) 252(WONT) 的情况下        if (ch == DO)//253 对端设备对本端设备的发出参数请求(如果支持对方的,则DO确认,不支持则DONT)        {            if (canshu == 32 || canshu == 35 || canshu == 39 || canshu == 36)            {                //发送命令码                byte[] sendcom = new byte[3];                sendcom[0] = 255;                sendcom[1] = 252;                sendcom[2] = Convert.ToByte(canshu);                //tcpsocket.Send(sendcom);                //steam.Write(sendcom,sendcom.Length);                Send(sendcom);            }            else if (canshu == 24)            {                //byte[] sendcom = { 255,240,78,65,87,83,32,8,2,5,255,240 };                byte[] sendcom = { 255,251,24 };                //steam.Write(sendcom,sendcom.Length);                Send(sendcom);            }            else if (canshu == 31)            {/*                255 250 31 window size                255 240 开始                recv SB N78A65W87S83 8(56)0(48) 2(50)5(53)                */                byte[] sendcom1 = { 255,31 };//同意窗口大小请求                Send(sendcom1);                //steam.Write(sendcom1,sendcom1.Length);                byte[] sendcom = { 255,250,31,80,25,240 };//发送窗口大小                //steam.Write(sendcom,sendcom.Length);                Send(sendcom);                //byte[] sendcoms = { 255,56,48,50,53,240};                //byte[] sendcoms = { 255,240 };                //sock.Send(sendcoms);            }            else if (canshu == 33)            {            }            else if (canshu == 1 || canshu == 34)            {                // 255 252 1        echo                byte[] sendcom = { 255,252,Convert.ToByte(canshu) };                //steam.Write(sendcom,sendcom.Length);                Send(sendcom);            }            else            {                string cuowu = canshu.ToString();//                string xx;//拍错用            }        }        else if (ch == DONT)//254 协商对端设备的参数(对端发出对本端参数的请求)        {        }        else if (ch == WILL)//251 本端设备的参数(发送给对方)        {            if (canshu == 3)            {            }            else if (canshu == 1 || canshu == 3)            {                //255 253 echo;                byte[] sendcom = { 255,253,sendcom.Length);                Send(sendcom);            }            else            {                //255 254 status{ }                byte[] sendcom = { 255,254,sendcom.Length);                Send(sendcom);            }        }        else if (ch == WONT)//252 本端设备的参数(发送给对方)        {        }        else if (ch == 250)        {            if (canshu == 24)            {                //byte[] sendcom = { 255,Convert.ToByte(canshu) };                // recv SB 24 0 ANSI                byte[] sendcom = { 255,24,73,240 };//发送终端编码send SB 24 0  ANSI                Send(sendcom);                //steam.Write(sendcom,sendcom.Length);                // recv SB 65 87 S[Unrecognized]                //recv SB NAWS 80 25                // IAC,SB,24,0,‘I‘,‘B‘,‘M‘,‘P‘,‘C‘, IAC,SE            }        }    }    /// <summary>    /// 保存log文件.这里个人需要, *** 作的就是本次的 str_data      /// </summary>    /// <param name="filePathname">绝对文件路径</param>    public voID Save_file(string filePathname)    {        string[] Str_dir = filePathname.Split(‘\‘);        string filePath_Dir = string.Empty;        for (int i = 0; i < Str_dir.Length - 1; i++)        {            filePath_Dir += Str_dir[i] + "\";        }        string filename = Str_dir[Str_dir.Length - 1];        Save_file(filePath_Dir,filename);    }    /// <summary>    /// 判断文件或目录是否存在    /// </summary>这是保存到当前程序运行到目录以今天日期生成目录    /// <param name="filePath_Dir">目录</param>    /// <param name="filename">文件名称</param>    private voID file_Exists(string filePath_Dir,string filename)    {        string filePathname = filePath_Dir + "\" + filename;        // string path = filePath_Dir + "\" + DateTime.Now.ToString("yyyy-MM-dd") + "\" + filePathname + ".txt";        if (!Directory.Exists(filePath_Dir))        {            Directory.CreateDirectory(filePath_Dir);        }        if (!file.Exists(filePathname))        {            fileStream fs = file.Create(filePathname);            fs.Close();        }    }    /// <summary>    /// 保存文件    /// </summary>    /// <param name="filePath_Dir">文件的目录</param>    /// <param name="filename">文件的名称</param>    public voID Save_file(string filePath_Dir,string filename)//保存文件函数    {        string filePathname = filePath_Dir + "\" + filename;        file_Exists(filePath_Dir,filename);        StreamWriter steam = new StreamWriter(filePathname,true,EnCoding.UTF8);        steam.Write(str_data);        steam.Close();    }    public voID close()    {        try        {            sock.Shutdown(SocketShutdown.Both);            sock.Close();        }        catch { }    }    //辅助类传递 接收数据,与socket    public class StateObject    {        // ClIEnt socket.          public Socket workSocket = null;        // Size of receive buffer.          public const int BufferSize = 1024;        // Receive buffer.          public byte[] buffer = new byte[BufferSize];        // Received data string.          public StringBuilder sb = new StringBuilder();        public string waitfor = string.Empty;    }}

}

@H_502_2@ 总结

以上是内存溢出为你收集整理的C# Telnet 类库代码,谨献给还在寻找C# Telnet类库的兄弟全部内容,希望文章能够帮你解决C# Telnet 类库代码,谨献给还在寻找C# Telnet类库的兄弟所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1214514.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存