C # telnet class library code, give it to the brothers who are still looking for c # telnet class libraries

C# Telnet class library code Today I installed a solid-state notebook for the notebook. The speed increase is obvious. I am very happy to send a Weibo as a souvenir. Self-taught C#, network, want to get a tool to facilitate daily work, I want to implement a tool for batch operation by myself. It's easy to think of and hard to do. Random investigation online. Thank you for "Telnet very useful class library-Wang Xiaozhuang's blog-CSDN blog" https://blog.csdn.net/weixin_42183571/article/details/80783268

This article gave me directions, code look. After N times, there is a lot of inspiration.
I didn’t understand the asynchrony in there. I didn’t understand asynchrony at the time, and it looked the same as the number of days. . . .
Any protocol has a negotiation process:
The telnet negotiation code is taken from Wang Xiaozhuang, with a small modification.

If there is no more BB, add the code.

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 project name
{
public class Telnet
{
#region // Direct copy of negotiated command code

// private byte[] receivebytes = new byte[1024]; //Accept
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 E SC = '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; // Define global variables for easy calling
< br /> //Define event
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 = "";// Received data
private StringBuilder str_data = new StringBuilder();// All received data
private StringBuilder Str_Temp = new StringBuilder();//The execution result of a single command is incomplete and actually useless
public bool Connected //Connection status< br /> {
get
{

if (sock != null)
{
return sock.Connected;
}
else
{
return false;
}

}
// get return = sock.Connected;
// set;
}
public string RecData //Get execution log
{
//get
//{ return str_data;
//}
get
{
return str_data.ToString();
}

}< br /> public string TempData //Get the log of each command execution, there is a problem, it is useless
{
//get
//{ return str_data;
//}
get
{
return Str_Temp.ToString();
}

}

#endregion
< br /> public Telnet(string IP)
: this(IP, 23) {} //Constructor chain
public Telnet(string IP, int port)// Main function of work
{
//IPAddress ipAddress = IPAddress.Parse("192.168.56.2");
IPAdd ress ipAddress = IPAddress.Parse(IP);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
sock = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
Console.WriteLine("connectDone.Rese: set to start connection without signal");
connectDone.Reset();
sock.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), sock);// Asynchronous connection
connectDone.WaitOne(10000, false);//Asynchronous blocking, the connection is successful, it will enter the next asynchronous connection, and the connection time will exceed 10S,

if (!connectDone.WaitOne(10000 , false))
{
sock.Close();//Connection failed, timeout exit;
Console.WriteLine("Connection failed, timeout exit");
}< br /> else // If the connection is successful, start receiving data.
{
//Start the thread of asynchronous acceptance
Thread threadread = new Thread(new ThreadStart(Receive));
threadread.Start();
}

}
///
/// The username and password are echoed back by default as ":"
///

/ //
///
///
///
public Telnet(string IP, int port,string username,string passwd)// Main function of work
: this(IP, port, username, passwd, ":", ":") //The two colons here are the echo of logging in to the connected device,
{

}
public Telnet(string IP, int port, string username, string passwd,string usernamewait,string passwdwait)// Main work function
{
//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: Set to start connection without signal");
connectDone.Reset();
sock.BeginConnect(remoteEP , new AsyncCallback(ConnectCallback), sock);// Asynchronous connection
connectDone.WaitOne(10000, false);

if (!connectDone.WaitOne(10000, false))
{
sock.Close();//If the connection fails, exit over time;
Console.WriteLine("Connection failed, exit over time");
}
else // if The connection is successful and start to receive data.
{
//Start the thread of asynchronous acceptance
Thread threadread = new Thread(new ThreadStart(Receive));
threadread.Start();
Send(usernamewait , username + " "); //Automatic connection configuration, you can manually
Send(passwdwait, passwd + " ");
}

}
public Telnet(string IP, int port,int timeout)// Main work function
{
//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: set to start connection without signal");
connectDone.Reset();
sock.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), sock);// Asynchronous connection< br /> connectDone.WaitOne(timeout*1000, false);

if (!connectDone.WaitOne(timeout * 1000, false))
{
sock.Close();//If the connection fails, exit over time;
Console.WriteLine("Failed connection, exit over time");
}
else // If the connection is successful, start Accept the data.
{
//Start the thread of asynchronous acceptance
Thread threadread = new Thread(new ThreadStart(Receive));
threadread.Start();
}

}
///
/// Asynchronous connection, asynchronous callback
///

///
private void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object. < br /> 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: set to signal");
connectDone.Set(); // Here is the connection event as a signal, the block in the main function will continue to execute, otherwise the 10s will time out
}
catch (Exception e)
{
Console.WriteLine("Asynchronous connection:" + e.ToString());
}
}
//Here is the method of receiving data
private void Receive()
{
try
{
// receiveDone.Reset();
//Receiving is useless to block, here is circular acceptance, yes Implemented in the callback
// Create the state object.
// Here is to check the msdn document, there is this, the main entry is to pass this auxiliary class, the main is to pass socke and state.buffer
StateObject state = new StateObject();
state.workSocket = sock;

// Begin receiving the data from the remote device.
sock.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
// receiveDone.WaitOne(10000,false);
//string ddd = string.Empty;< br /> }
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
//Receive data asynchronous callback
private void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
//Getting the sock is actually unnecessary, because socket is a global variable
int bytesRead = client.EndReceive(ar);

if (bytesRead > 0)
{
////Create a byte[]
Byte[] mToProcess = new Byte[bytesRead];
Array.Copy( state.buffer, mToProcess, bytesRead);//Array copy

Str_Temp = ProcessOptions(mToProcess);//Clean the command code and get the actual data returned
// Console.WriteLine ("*********************************************");
Console.Write(Str_Temp);//Echo the data of this time
// Console.WriteLine("******************** **************** *********");
// response = mOutText;
str_data.Append(Str_Temp); //All data, add the data received each time to str_data. It is used to save the log later
string temps = str_data.ToString();//Here is the breakpoint to test each time the data is obtained, so I don’t want to delete it.

client.BeginReceive(state.buffer, 0 , StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);

//The next step is the key to obtaining data in a loop. Each time the data is received, a new one starts again. data.
}
else
{

//Here is the received data is 0, when the normal asynchronous received data is 0, there should be no data blocking state, no To this place.
Console.WriteLine("Accepted data is less than 0:" + "An exception occurred");
client.Close();//Close the connection
}
}
catch (Exception e)
{
Console.WriteLine("Accept data exception" + e.ToString());//Here is the code for catching the exception. Generally, when the telnet is over, the blocking state is processed asynchronously, and sometimes it will be sent, which is useless.
}
}

// The method of sending commands, the data here is without carriage return,
public void Send(String data)
{
try
{

byte[] byteData = Encoding.ASCII.GetBytes(data);
//Asynchronous sending
sock.BeginSend( byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), sock);
//Asynchronous blocking, continue to execute after the transmission is completed, if the block is not completed, you can add the timeout sendDone.WaitOne (10000,false);
sendDone.WaitOne();

}
catch
{
Console.WriteLine("An exception occurred: {0} ", data + " ");
}
finally
{
//client.Shutdown(SocketShutdown);
}
}
public void Send(char data)
{
char[] char_data = {data };
try
{
byte[] byteData = Encoding. ASCII.GetBytes(char_da ta);
sock.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), sock);
sendDone.WaitOne();
}
catch
{
Console.WriteLine("An exception occurred: {0}", data + " ");
}
finally
{
//client.Shutdown(SocketShutdown);
}
}
public void Send(char[] data)
{

try
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
sock.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), sock);
sendDone.WaitOne();
}
catch
{
Console.WriteLine("Exception: {0}", data + " ");< br /> }
finally
{
//client.Shutdown(SocketShutdown);
}
}
public void Send(byte[] byteData)
{

tr y
{
//byte[] byteData = Encoding.ASCII.GetBytes(data);
sock.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), sock);
sendDone.WaitOne();
}
catch
{
Console.WriteLine("An exception occurred while sending bytedata: {0}", byteData.ToString () + " ");
}
finally
{
//client.Shutdown(SocketShutdown);
}
}< br /> ///
/// The method of executing the command, judging the echoed character, and executing the command
///

/// Echo string judgment
/// Judge the command executed successfully
/// The delay in executing the command
public void Send(string expect, string command, int delay_time)
{
// string local_data = string.Empty ;
int i = 0;

while (true)
{
//This is mainly to judge the data in str_data, the received data will continue to be written into this, acceptance may be Delay, plus cycle judgment, if (str_data.ToString().TrimEnd().EndsWith(expect))
{
Thread.Sleep(delay_time);//The delay of executing the command
Send(command) ;
break;

}
else
{// Increase the penalty value for the failure of the command execution code to determine the failure. After 8 times, the current received data has not yet appeared Judged string, socket is closed
i++;
}
Thread.Sleep(1000);// If no judged character appears in the current received data, wait 1s and judge again
if(i==8)
{
//Console.WriteLine("Command execution error, wrong command" + command + "Command execution result:");// + str_data.ToString( ));
//Console.WriteLine();
// Console.WriteLine("Command execution error, wrong command"+ command+"Command execution result:" +str_data.ToString());< br /> // str_data.Append("Abnormal termination");
sock.Close ();
break;

}
// }

}
}
///
/// The method of executing the command, the default delay is 500ms.
///

/// Echoing string judgment
/// Command to determine successful execution
public void Send(string expect, string command)
{
Send(expect, command, 100);

}

private static void SendCallback(IAsyncResult ar)
{//Send data asynchronously
try
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
sendDone.Set();

}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}

///
/// Cleaning command code. The core code of telnet
///

///
///
private StringBuilder ProcessOptions(byte[] resbyte)
{//Network income

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
{
//Convert data from byte[] to string
for (int i = 0; i {
Char ss = Convert.ToChar(resbyte[i]);
m_strTemp = m_strTemp + Convert.ToString(ss);
}

//The meaning here is, when the data is not traced, perform a scan
while (bScanDone != true)
{
//Get the length
int lens mk = m_strTemp.Length;
//Then start analyzing instructions, because each instruction starts with 255, so you can use this to distinguish each instruction
ndx = m_strTemp.IndexOf(Convert.ToString(IAC ));//The position where IAC first appeared

//This is an error judgment, which has no other meaning
if (ndx> lensmk)
ndx = m_strTemp.Length;

//Here, if you find the telnet command marked by IAC, perform the following steps
if (ndx != -1)
{
#region If there is an IAC flag bit
// Assign the characters of the flag bit IAC to the final display text
m_DISPLAYTEXT += m_strTemp.Substring(0, ndx);
// Get the command code here
br /> ch = m_strTemp[ndx + 1];//Get the command code
canshu = m_strTemp[ndx + 2];//Get the command code

//If the command code is 253 (DO) 254(DONT) 521(WILL) 252(WONT)
if (ch == DO || ch == DONT || ch == WILL || ch == WONT)
{
//Store the entire command consisting of 3 characters at the beginning of IAC
//m_strOption = m_strTemp.Substring(ndx, 3);
//m_ListOptions.Add(m_strOption);

// Assign the character of the flag bit IAC to the final display text
//m_DISPLAYTEXT += m_strTemp.Substring(0, ndx);

//Delete the processed string
string txt = m_strTemp.Substring(ndx + 3);< br /> m_strTemp = txt;
telnetproceess(ch, canshu);
}
//If IAC is followed by another IAC (255)
else if (ch == IAC)
{
//The display starts from the beginning of the input string and ends with the previous IAC
//m_DISPLAYTEXT += m_strTemp.Substring(0, ndx);
//Exclude the processed string afterwards
m_strTemp = m_strTemp.Substring(ndx + 1);
string xxc = m_strTemp;
}
//If IAC is followed by Is SB(25 0)
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
}
//If there is no IAC flag in the string
else
{
//Display information accumulates the fields stored by m_strTemp
m_DISPLAYTEXT = m_DISPLAYTEXT + m_strTemp;
bScanDone = true;
}
}< br /> //Output the information that people see
m_strNormalText.Append(m_DISPLAYTEXT);
}
catch (Exc eption eP)
{
throw new Exception("Error parsing the incoming string:" + eP.Message);
}
return m_strNormalText;

}
//Asynchronous delegate call, here is the negotiation code, no problems were found when testing many devices
private void telnetproceess(char ch, char canshu)
{
//If the command code is 253(DO) 254(DONT) 251(WILL) 252(WONT)
if (ch == DO)//253 The peer device sends a parameter request to the local device ( If you support the other party, DO confirm, if not, then DONT)
{
if (canshu == 32 || canshu == 35 || canshu == 39 || canshu == 36)
{
//Send command code
byte[] sendcom = new byte[3];
sendcom[0] = 255;
sendcom[1] = 252;< br /> sendcom[2] = Convert.ToByte(canshu);
//tcpSocket.Send(sendcom);
//steam.Write(sendcom, 0, sendcom.Length);
Send(sendcom);

}
else if (canshu == 24)
{
//byte[] sendcom = {255, 240, 78, 65, 87, 83, 32, 8, 0, 32, 2, 5, 255, 240 };
byte[] sendcom = {255, 251 , 24 };
//steam.Write(sendcom, 0, sendcom.Length);
Send(sendcom);
}
else if (canshu == 31)< br /> {/*
255 250 31 window size
255 240 start
recv SB N78A65W87S83 8(56)0(48) 2(50)5(53)
* /
byte[] sendcom1 = {255, 251, 31 };//Agree to the window size request
Send(sendcom1);
//steam.Write(sendcom1, 0, sendcom1.Length );
byte[] sendcom = {255, 250, 31, 0, 80, 0, 25, 255, 240 };//Send window size
//steam.Write(sendcom, 0, sendcom.Length);
Send(sendcom);
//byte[] sendcoms = {255, 250, 31,78, 65,87,83, 32,56,48,32,50, 53,255,240};
//byte[] sendcoms = {255, 250, 31, 78 , 65, 87, 83, 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, 0, sendcom.Length);
Send(sendcom);
}

else
{
string cuowu = canshu.ToString();//
string xx;//Wrong use
}

}< br /> else if (ch == DONT)//254 Negotiate the parameters of the peer device (the peer sends a request for the local parameters)
{

}
else if (ch == WILL)//251 The parameters of the local device (send to the other party)
{
if (canshu == 3)
{
}
else if (canshu == 1 || canshu == 3)
{
//255 253 echo;
byte[] sendcom = {255, 253, Convert.ToByte(canshu) };
//steam.Write(sendcom, 0, sendcom.Length);
Send(sendcom);
}
else
{
//255 254 status{ }
byte[] sendcom = {255, 254, Convert.ToByte( canshu) };
//steam.Write(sendcom, 0, sendcom.Length);
Send(sendcom);
}

}
else if (ch == WONT)//252 The parameters of the local device (send to the other party)
{

}
else if (ch == 250)
{
if (canshu == 24)
{
//byte[] sendcom = {255, 254, Convert.ToByte(canshu) };
// recv SB 24 0 ANSI
byte[] sendcom = {255, 250, 24, 0, 65, 78, 83, 73, 255, 240 };//Sending terminal code send SB 24 0 ANSI
Send( sendcom);
//steam. Write(sendcom, 0, sendcom.Length);
// recv SB 65 87 S[Unrecognized]
//recv SB NAWS 80 25
// IAC, SB, 24, 0, 'I','B','M','P','C', IAC, SE

}
}

}

///
/// Save the log file. For personal needs here, the operation is str_data this time.
///

/// absolute file path
public void Save_File(string FilePathName)
{
string[] Str_dir = FilePathName.Split('\');
string FilePath_Dir = string.Empty;
for (int i = 0; i {
FilePath_Dir += Str_dir[i] + " \";
}
string FileName = Str_dir[Str_dir.Length-1];
Save_File(FilePath_Dir, FileName);
}

/ //
/// Determine whether the file or directory exists
///
This is to save to the current program and run to the directory to generate the directory with today’s date
/// Directory
// / file name
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();
}
}
/// < br /> /// Save the file
///

/// The directory of the file
/// the name of the file
public void Save_File(string FilePath_Dir, string FileName)//Save file function
{
string FilePathName = FilePath_Dir + "\" + FileName;
File_Exists(FilePath_Dir, File Name);
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 {}
}
//Auxiliary class transmits and receives data, and 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;
}

}

}

Leave a Comment

Your email address will not be published.