telnet控制路由器交换机与微信公众平台

原来控制每个机房上网都是从交换机web管理页面来操作开关端口的,自从单位换了锐捷的路由和交换机以后就坑爹了,连web管理都没有,开关端口啥的都要每次登陆telnet,一堆指令,后来我弄了个微信公众平台就琢磨着用公众平台来控制开关端口,实现后效果杠杠的,我微信输入101open,101的网就开了,101close,101的网就断开了,在家在单位,在地铁,在厕所......随便控制 立马有效        现在的思路就是     微信发指令到服务端->服务端写操作信息到数据库->服务器上的指令执行器读取数据库中的指令执行完成后保存结果   

 

telnet  类

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


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 = "";
    //====================================================            

    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);
                    //=================================================
                    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编码。
    /// </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;
    }
}


 

 执行端telnet控制   大概就这个意思,试下来效果很好,很稳定

-----------------------------------------------

  

 Telnet p = null;

private void DoTelnet(string port, string order)           //输入 端口   指令(开或关)
        {
            if (String.IsNullOrEmpty(port) || String.IsNullOrEmpty(order))
            {
                textBox1.Text += "参数缺失-----" + DateTime.Now.ToString() + "\r\n";
            }
            else if (prv_port == port&& prv_order == order)      //排除重复执行相同指令
            {
                textBox1.Text += "指令重复执行-----" + DateTime.Now.ToString() + "\r\n";
            }
            else
            {
                while (p == null || p.Connect() == false)
                {
                    textBox1.Text += "连接失败,可能超过规定的连接数量-----" + DateTime.Now.ToString() + "\r\n";
                    p = new Telnet("你路由的ip地址", 23, 30);
                }

                //等待指定字符返回后才执行下一命令
                p.WaitFor("Username:");
                p.Send("路由的用户名");
                p.WaitFor("Password:");
                p.Send("路由的密码");
                p.WaitFor("router01#");
                p.Send("telnet 交换机的ip");
                p.WaitFor("Password:");
                p.Send("交换机的密码");
                p.WaitFor("switch01>");
                p.Send("en");
                p.WaitFor("Password:");
                p.Send("交换机的enable密码");
                p.WaitFor("switch01#");
                p.Send("config t");
                p.WaitFor("switch01(config)#");
                string s = "int gigabitEthernet " + port;
                p.Send(s);
                s = "switch01(config-if-GigabitEthernet " +port+ ")#";
                p.WaitFor(s);
                if (order == "open")
                {
                    p.Send("no shutdown");
                }
                else
                {
                    p.Send("shutdown");
                }
                p.Send("exit");
                p.Send("exit");
                p.Send("exit");
                p.Send("quit");
               
                prv_port= port;
                prv_order = order;
                textBox1.Text += port + ":" + order + "执行完成-----" + DateTime.Now.ToString() + "\r\n";
            }
        }


 

 

 

 

你可能感兴趣的:(telnet控制路由器交换机与微信公众平台)