Telnet客户端

今天早上根据网友夏春涛的代码,整理了一下,做了一个telnet客户端。利用Socket建立与服务器(cisco路由器)的管道,然后输入指令,接收回发的数据,并进行数据处理。

不过还是有一些bug,以后继续完善。

 代码链接:https://files.cnblogs.com/futureflare/GaoTelnet.rar

主要的一些函数:

OnRecievedData
/// <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 != "")
{
strWorkingData
= mOutText;
strFullLog
+= mOutText;

}
//接收完数据,处理完字符串数据等一系列事物之后,开始回发数据
RespondToOptions();
}
catch (Exception ex)
{
throw new Exception("接收数据的时候出错了! " + ex.Message);
}
}
else// 如果没有接收到任何数据的话
{
// 关闭连接
// 关闭socket
sock.Shutdown(SocketShutdown.Both);
sock.Close();
}
}
catch { }
}
ProcessOptions
/// <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;
}
posted @ 2011-06-21 13:01  InFuture  阅读(567)  评论(0编辑  收藏  举报