当前位置:文档之家› 用Socket编程来实现Telnet协议

用Socket编程来实现Telnet协议

ok,翻协议,弄清原理,结果比预想的难度要大一些
定义 ============================================================ Telnet 协议是 TCP/IP 协议族中应用最广泛的协议。 它允许用户(Telnet 客户端)通过一个协商过程来与一个远程设备进行通信。 Telnet 协议是基于网络虚拟终端 NVT(Network Virtual Termina1)的实现, NVT 是虚拟设备,连接双方(客户机和服务器)都必须把它们的物理终端和 NVT 进行相互转 换 ============================================================
用 Socket 编程来实现 Telnet 协议 这因为有个任务涉及到使用 telnet 来连接远端的路由器,获取信息,之后进行处理. 所以需要写一个自动 telnet 登录到远端,之后获取信息进行处理的程序.
自己 C++ 一塌糊涂,所以几乎最开始就没打算用 C++或者 C 写 论自己的实力,还是走 C#路线稍微稳妥一点吧, 因为 telnet 是使用 tcp/ip 协议折腾的事情 很容易的想到使用 socket 来实现 telnet (当然你可以在进程里启用 telnet 命令,只不过总觉得那样不够技术, 而且操作不自由--受限于 telnet 这个指令)
*/ s.Blocking = false;
/* * 开始一个对远程主机连接的异步请求, * 因为 Telnet 使用的是 TCP 链接,是面向连接的, * 所以此处 BeginConnect 会启动一个异步请求,
(本文下载自防锈油文档综合站 www.hthrt.com。转载请说明出处)
* 请求获得与 给的 address 的连接 *
* 此方法的第二个函数是一个类型为 AsyncCallback 的委托 * * 这个 AsyncCallback msdn 给出的定义如下 * =================================================================== * 使用 AsyncCallback 委托在一个单独的线程中处理异步操作的结果。A * syncCallback 委托表示在异步操作完成时调用的回调方法。 * 回调方法采用 IAsyncResult 参数,该参数随后可用来获取异步操作的结果。 * =================================================================== * 这个方法里的委托实际上就是 当异步请求有回应了之后,执行委托的方法.
public class Program {
#region 一些 telnet 的数据定义,先没看懂没关系
/// <summary> /// 标志符,代表是一个 TELNET 指令 /// </summary> readonly Char IAC = Convert.ToChar(255); /// <summary> /// 表示一方要求另一方使用,或者确认你希望另一方使用指定的选项。 /// </summary> readonly Char DO = Convert.ToChar(253); /// <summary>
ok,原理就是那么回事,讲讲细节吧
telnet 来连接的时候,需要发送一系列的指令来协商(绵羊协商)通信, 流程图类似这个
ok,那么,具体的命令是怎样的呢? 很无趣的, 就是 telnet 的命令格式
IAC
命令码
一个个的解释.
选项码
IAC:命令解释符,说白了就是每条指令的前缀都得是它,固定值255 (11111111 B)
类似那个经典的英国绵羊笑话 使用英文描述两只绵羊在路上碰到后发生的故事 =========================
绵羊 A: Hi,Sheep! 绵羊 B:Hi, Can you speak Chinese? 绵羊 A:yes, "jin tian chi le ma ? (今天吃了吗?)" 绵羊 B: "chi la ,hen shuang ! (吃啦,很爽!)" .....省略500字 改卷的英国人累牛满面,因为他不会中文, 但又不能说这篇文章有问题. ========================= 这里英文就可以理解为 NVT 的标准功能,为通用语, 而后来的中文拼音,就是扩展.
由于 NVT 得顾及到所有的各种型号的机器,所以他定义的 操作十分有限 (因为考虑到包括要支持类似9城小****那些性能很差,系统简单的机器), 为了解决 NVT 这个"为了照顾小****,而导致高端设备的功能不能用"的这个弊病, Telnet 琢磨出了一个比较好的解决方案 "用于扩展基本 NVT 功能的协议,提供了选项协商的机制" 来解决问题
245
异常中止输出
AYT
246
对方是否还在运行?
EC
247
转义字符
EL
248
删除行
GA
249
继续进行
SB
250
子选项开始
WILL
251
同意启动(enable)选项
WONT
252
拒绝启动选项
DO
253
认可选项请求
DONT
254
拒绝选项请求
选项协商:4种请求 1)WILL:发送方本身将激活选项 2)DO:发送方想叫接受端激活选项 3)WONT:发送方本身想禁止选项
大概意思就是 跟远端通信的一套协议,之后这个协议无视你机器是啥型号,啥样子 只要是用 telnet 的,统统都可以看成是 NVT (类似面向对象中的继承关系:NVT 是父类,各种实用 telnet 的都继承与 NVT)
好处非常明显,可以无视型号而直接使用标准命令,任何服从 NVT 的设备都能通信 当然不可避免的,标准也同时代表着性能的损失:
/// 存储准备发送的信息 /// </summary> string m_strResp;
/// <summary> /// 一个 Socket 套接字 /// </summary> private Socket s; #endregion
/// <summary> /// 主函数 /// </summary> /// <param name="args"></param> static void Main(string[] args) {
//实例化这个对象 Program p = new Program();
//启动 socket 进行 telnet 链接 p.doSocket();
}
/// <summary> /// 启动 socket 进行 telnet 操作 /// </summary>
private void doSocket() {
/// </summary> byte[] m_byBuff = new byte[100000];
/// <summary> /// 收到的控制信息 /// </summary> private ArrayList m_ListOptions = new ArrayList();
/// <summary>
4)DONT:发送方想让接受端去禁止选项 紧接着就是选项码
选项标识
名称
1
回显
3
抑制继续进行
5
状态
6
定时标记
24
终端类型
31
窗口大小
32
终端速度
33
远程流量控制
34
行方式
36
环境变量
ok,为了搞掂这个 telnet 链接, 我特地装了个 linux 作为 telnet 的链接对象进行 telnet 远程登录 之后写了一个恶心的代码来帮助我进行调试
命令码: 一系列定义:(最常用的250~ 254 咱加粗表示)
名称
代码(十进制) 描述
EOF
Baidu Nhomakorabea
236
文件结束符
SUSP
237
挂起当前进程(作业控制)
ABORT
238
异常中止进程
EOR
239
记录结束符 i
SE
240
自选项结束
NOP
241
无操作
DM
242
数据标记
BRK
243
中断
IP
244
中断进程
AO
额,在写这个程序之前 ,我搜了将近1天时间的网路 发现大多数代码注释的不是太和谐,读起来很难理解 所以自己根据网上的一个 win 程序改出了一个 console 的程序
同时,我特地花了两天时间,几乎把每一句能写注释的都写了, 基本上可以说是我目前注释写的最多的一次代码了,
代码特别庞大,就做个窗口放上去了
(本文下载自防锈油文档综合站 www.hthrt.com。转载请说明出处)
/* * 说明此 socket 不是处于阻止模式
* * msdn 对阻止模式的解释: * ============================================================ * 如果当前处于阻止模式,并且进行了一个并不立即完成的方法调用, * 则应用程序将阻止执行,直到请求的操作完成后才解除阻止。 * 如果希望在请求的操作尚未完成的情况下也可以继续执行, * 请将 Blocking 属性更改为 false。Blocking 属性对异步方法无效。 * 如果当前正在异步发送和接收数据,并希望阻止执行, * 请使用 ManualResetEvent 类。 * ============================================================
//获得链接的地址,可以是网址也可以是 IP Console.WriteLine("Server Address:"); //解析输入,如果是一个网址,则解析成 ip IPAddress import = GetIP(Console.ReadLine()); //获得端口号 Console.WriteLine("Server Port:"); int port = int.Parse(Console.ReadLine());
readonly Char WONT = Convert.ToChar(252);
/// <summary> /// 表示后面所跟的是对需要的选项的子谈判 /// </summary> readonly Char SB = Convert.ToChar(250);
/// <summary> /// 子谈判参数的结束
//建立一个 socket 对象,使用 IPV4,使用流进行连接,使用 tcp/ip 协议 s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//获得一个链接地址对象(由 IP 地址和端口号构成) IPEndPoint address = new IPEndPoint(import, port);
using System; using System.Collections.Generic; using System.Text;
using System.Net; using System.Net.Sockets; using System.Collections;
namespace ConsoleApplication1 {
/// 表示一方要求另一方停止使用,或者确认你不再希望另一方使用指定的选项。 /// </summary> readonly Char DONT = Convert.ToChar(254); /// <summary> /// 表示希望开始使用或者确认所使用的是指定的选项。 /// </summary> readonly Char WILL = Convert.ToChar(251); /// <summary> /// 表示拒绝使用或者继续使用指定的选项。 /// </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> /// 流
相关主题