关于telnet协议的研究及应用续

来源:互联网 发布:vc编写c语言win10 编辑:程序博客网 时间:2024/05/16 10:12
  • telnet协议回顾
           在了解telnet协议的过程时,首先要了解telnet协议本身,选项协商是前提(是否打开或关闭相应的选项),子选项协商(终端类型,窗口大小),知道这些后再去了解终端类型,所谓的终端类型只是输出和输入的数据与在不同系统之间特殊键的转换过程。
  • 对终端类型的了解
          从我开始接触telnet时,并不知道所谓的终端类型,最简单的方法就是选项全部拒绝(用的是最基本的终端类型,只能区分telnet协商命令和数据),当在调试系统时出现特殊字符不能解析,才知道对于当连接windows的telnet服务器时把自己的终端配成vt220,连接linux版的telnet服务器时把自己终端类型配成vt100,就能解决特殊字符的问题。

       但是,到现在知道所谓终端类型后,就一直坚信只要实现了一种终端类型,那么就能连接所有支持该终端类型的telnet服务器。于是乎,在网上查了下,才知道vt100是当下很流行的终端,因此决定一试。

  • vt100初体验
            当了解了所谓的终端后,决定实现一个vt00,使telnet客户端可以连接所有的系统。于是乎,首先从网上找相应的资料,发现讲述vt100终端的很少,而且大部分都是英文,我找了好久,找到了一个关于vt100控制码的说明,如下:

http://blog.csdn.net/chaofanwei/article/details/17918619


        看起来,实现的话有点难度,于是,先放下,在网上又找了好久,发现据说有一个就telnet,实现了vt100,于是从sourceforge上下载了下来,开始读源代码,但是我最终发现有一个确实有一个类实现了vt100(能够执行命令-windows和linux),但是当我仔细分析代码以及用wireshark对网络包进行分析时,根本就没有把终端类型vt00发送给服务器,而是用的最基本的终端类型,于是我打算把jtelnet结合我对telnet的理解修改下,于是我给代码加上了vt100的终端协商,客户端最后也如愿以偿的把终端类型vt100发送给了服务器,命令也可以正常运行。
   

       于是,我想着把jtelnet执行的结果给抠出来打印到控制台里面就能满足需求,于是我开始研究,但最后确发现jtelent的vt100实现是画在屏幕上的。所谓的画即每个字符都有相应的x,y坐标,然后画到相应的位置(vt100格式)。这里所说的画其实是windows版的telnet服务器发送过来的每个字符都是带有坐标的(没有\r\n),而linux版的telnet服务器是没有发送坐标的(含有\r\n),这就给vt100的实现带来了难处,vt100的实现需要自己考虑并处理服务器发送过来的数据,而jtelnet也确实实现了。
        但这个时候有一个问题,就是因为windows服务器给你发送过来的数据是带有坐标的,因此服务器会用一个默认的值(宽80,高24)来表示客户端窗口的大小,当发送的数据超过客户端的高度或者客户端数据的高度要超过窗口高度时,服务器会把此屏幕的数据再全部发送一下,但是是一个往上推的过程,超过的部分就没有了,即只显示当前窗口大小最近的内容,超过的部分被推掉不显示。由此一个问题便产生了当服务器一次发送过来的数据大于客户端高度时,比如执行一个dir命令,当文件数很多时,因为窗口高度有限,这个时候我们只能看到最下面的几行数据,高处的数据就会被掩盖,这样便会得到不正确的结果(一部分数据)。
        这个问题又困扰了我好久,最后我又开始开telnet协议,发现有一个子选项可以协商窗口大小,因此我用上一篇的方法设置了窗口大小,我的思路就是把窗口大小给设置成最大值,这样可以使在数据不超过最大值的情况下,数据之后向下累加,而不会超出高度被推掉的情况。最后我成功的设置了窗口大小到2400,我以为我成功了,但当我多次执行命令时,却发现服务器发过来的数据还是被推掉了,又从0行开始了,这个时候我发现才执行了70行左右,远没有超过2400,于是我结合telnet协议关于窗口大小子选项的说明,服务器可以拒绝设置相应窗口大小,因此设置大窗口并不靠谱。
       到现在,头已经很大了,困扰我好久的telnet不断给我出难题。
       至于上面的问题,还有一个方法待研究,就是在每次发送执行命令后,执行一个清屏命令(cls)。

 

  • 现在采取的实现
            至于我们现在的telnet实现,我是想来一个投机取巧的方法,因为现在对我们来说当是linux服务器,把终端类型设置成vt100(结合jtelnet),windows服务器时把终端类型设置成vt220,就可以完美解决。至于投机取巧,是因为我发现windows服务器是在用户输入用户名密码后才向客户端请求终端类型,而且在这之前会给客户端发送标准的logo “欢迎使用 Microsoft Telnet Client”,我就是根据是否含有Microsoft来判断是否是windows的,如果是windows,就把终端类型在请求前改成vt220,否则的话就默认设置为vt100,完美解决。
            对于怎么判断命令是否结束,我现在的实现就是在每次发送命令时,在命令最后再加上一条echo命令,echo变量名加一个序列号,判断变量值和序列号来判断命令是否结束。

 附件:

 

 

linux中执行 pwd

112 119 100 13 10
 p   w   d
47 104 111  109  101 47 98  111 99 111 13 10
/   h   o    m     e  /  b   o   c  o
98 111 98 111 64 98 97 98 121 58 126 36 32
b   o   b  o   @  b  a  b  y   :  ~   $  

 

windows 有d盘切换到e盘时跟踪
27   91 54 59 53 72 101 0  
ESC  [   6  ;  5  H  e  NUT 

27   91 54 59 54 72
ESC  [   6  ;  6  H

27   91 54 59 54 72 58   0   
ESC  [   6  ;  6  H  :  NUT

27   91 56 59 49  72   69  0    58   0  92   0   62   0 
ESC  [   8  ;  1   H    E  NUT   :  NUT  \  NUT   >  NUT

27   91  56  59  53  72 
ESC  [    8  ;    5   H    

 

 

0 0
原创粉丝点击