找回密码
 加入
搜索
查看: 16974|回复: 10

[网络通信] [Telnet]关于通过TCP来执行telnet命令从返回值判断是否成功问题.

  [复制链接]
发表于 2012-9-10 16:52:06 | 显示全部楼层 |阅读模式
本帖最后由 小熵 于 2012-9-11 09:36 编辑

呼叫 olala,呼叫pcbar,呼叫各位大神...
另外一类似问题
http://www.autoitx.com/forum.php ... mp;highlight=telnet

在论坛看了TCPsend来进行Telnet,按照一下代码进行之后,提示4个问号,并提示"Cannot connect2"

使用au3检测返回信息的是什么弄的?一部分吗?(If StringInStr($ack, "login:") >= 1 Then ;)

用CMD做telnet之后提示
CentOS Linux release 6.0 (Final)
Kernel 2.6.32-71.el6.i686 on an i686
login:

登录之后提示
Last login: Mon Sep 10 16:34:06 from 172.28.101.1
-bash: /sbin:/usr/sbin:/usr/local/sbin:/usr/kerberos/sbin: 没有那个文件或目录
[sunkaizhan@genuine-opto-bob ~]$

au3代码
Global $host, $port, $delay, $user, $pass, $sk, $ack
$host = "172.28.101.9";交换机IP
$port = 23;telnet默认端口
$delay = 500 ; 等待时间/毫秒
$user = "test";用户名
$pass = "123456";密码
 
TCPStartup()
$sk = TCPConnect($host, $port)
 
If $sk = -1 Then
MsgBox(0, "", "Cannot connect1")
Exit
EndIf
 
Sleep($delay)
$ack = TCPRecv($sk, 150)
TrayTip("", $ack, 10)
 
 MsgBox (0,"",$ack)
 
If StringInStr($ack, "login:") >= 1 Then ;如果连接成功,设备返回有关信息
;下面将发送用户名
Sleep($delay)
TCPSend($sk, "y" & @CRLF)

Sleep($delay)
TCPSend($sk, $user & @CRLF)
Sleep($delay)
$ack = TCPRecv($sk, 80)
TrayTip("", $ack, 10)
; 和密码
Sleep($delay)
TCPSend($sk, $pass & @CRLF)
Sleep($delay)
$ack = TCPRecv($sk, 80)
TrayTip("", $ack, 10)
Else
MsgBox(0, "", "Cannot connect2")
Exit
EndIf
 
If StringInStr($ack, "[root@test ~]$") = 0 Then ; 登陆成功后设备返回的信息
MsgBox(0, "Error", "Access denied")
Exit
EndIf
 
; 下面你可以发送一些命令给设备,比如重启
Sleep($delay)
TCPSend($sk, "dir" & @CRLF)
Sleep($delay)
$ack = TCPRecv($sk, 2000)
MsgBox(0,"Running processes", $ack)
 
TCPCloseSocket($sk)
TCPShutdown()
Exit
发表于 2012-9-10 17:28:30 | 显示全部楼层
本帖最后由 xiehuahere 于 2012-9-11 09:34 编辑

回复 1# 小熵

一直在用,所以封装了两个函数SendLine和WaitFor。
本来想发到UDF区的,不过之前发了个FTP的UDF没多少人感兴趣,看来这里跟网络设备打交道的人比较少。所以直接贴这里吧。
试试,有问题反馈。不过我估计应该没什么问题了,毕竟经过了我们可靠性测试几百万次的验证。
不过对于发送命令的最大长度没试验过,一般命令都不会很长,过长的我都封装到shell脚本中然后再用SendLine调用脚本远程执行了。
  
Global $buff  ; to hold the received content
 
;=================================================================
; Name: SendLine
; Description: Send one command line (@CRLF added automatically)
; Return value: 0 - Success
;          -1 - Failure
;=================================================================
Func SendLine($string)
        TCPSend($socket, $string & @CRLF)
        If @error Then
                ;Local $result = DllCall("Ws2_32.dll", "int", "WSAGetLastError")
                ;Return $result[0]
                 Return -1
        EndIf
        Return 0
EndFunc
  
;=================================================================
; Name: WaitFor
; Description: Wait for desired output. Use it after each TCPSend() to make
;        buff always hold the latest content
; Return value: 0 - Success
;        -1 - Failure
;=================================================================
Func WaitFor($string, $timeout=2000)
        Local $recv = ""
        $buff = ""        
        If $string <> "" Then
                $timer = TimerInit()
                Do
                        $recv &= TCPRecv($socket, $buffSize)
                        If @error <> 0 Then Return -1
                        If $recv == "" Then
                                Sleep(20)
                        Else
                                $buff &= $recv
                        EndIf
                        If TimerDiff($timer) > $timeout Then Return -1
                Until StringInStr($buff, $string) > 0
        EndIf
        Return 0
EndFunc
发表于 2012-9-10 17:32:34 | 显示全部楼层
本帖最后由 xiehuahere 于 2012-9-11 09:24 编辑

Init函数和_CleanOnExit函数,建立和释放设备连接用。
Local Const $username = "root", $password = "123456"
Local $server, $socket = -1
Local $buff = "", $buffSize = 500  ;for receiving ack
  
OnAutoItExitRegister("_CleanOnExit")
  
Func Init()
        TCPStartup()
        $socket = TCPConnect($server, 23) ; 23 - telnet port
        If @error Then Return -1
        
        ; Verify if it's login request
        If WaitFor("login") = -1 Then Return -1

        ;Send username
        If SendLine($username) = -1 Then Return -1

        If WaitFor("assword") = -1 Then
                ;Handle the case that password is removed
                If StringInStr($buff, "# ") = 0 Then
                        $needPW = False
                Else
                        Return -1
                EndIf
        EndIf
        
        If $needPW Then
                ;Send password
                If SendLine($password) = -1 Then Return -1
                If WaitFor("# ") = -1 Then Return -1
        EndIf
        Return 0
End Func
 
Func _CleanOnExit()
        If $socket <> -1 Then TCPCloseSocket($socket)
        TCPShutdown()
EndFunc
 楼主| 发表于 2012-9-11 08:30:26 | 显示全部楼层
FTP的还好点,FTP可以用-s参数执行写在文本文件里面的命令..
 楼主| 发表于 2012-9-11 08:54:33 | 显示全部楼层
本帖最后由 小熵 于 2012-9-11 08:57 编辑

看了一下,还是有点摸不着头脑,不知道把这2段加在哪里...好像在上面定义的是$sk,你在函数里面定义的是$soket
其实我就是想telnet到一台服务器上,登录,输入一个show的命令,然后从返回的字符串中间截取一个值,查看是否大于60,如果大于60,就执行一条命令,如果没有达到60,则继续循环检查这个值...

telnet ip之后返回的是
CentOS Linux release 6.0 (Final)
Kernel 2.6.32-71.el6.i686 on an i686
login:

登录之后返回的是
Last login: Mon Sep 10 16:46:10 from 172.28.101.105
[sonny@test ~]$

执行查询命令返回的是:
abc 62

这个62大于60,所以执行一条命令

要求后台执行,不影响用户操作..
发表于 2012-9-11 09:04:05 | 显示全部楼层
本帖最后由 xiehuahere 于 2012-9-11 09:30 编辑

$sk和$socket只是变量名的区别,自己改改就是了。

执行命令用SendLine函数;接收返回内容用WaitFor函数(等待感兴趣的字符串,你这里如abc),接收到的字符串存在$buff这个全局变量中。(见2#)
如果接收超时,WaitFor函数会返回-1。

每次SendLine后用WaitFor将内容收走,以保证此后每次接收的都是最新内容。(使用示例见3#)
你这里的命令提示符是“$”(非root权限),所以你在接收时要用"$ "来代替我代码中的"# "(之所以后面加个空格是为了防止你的命令输出中也含有这个字符,以免跟命令提示符混淆)。
   
你用MsgBox或ConsoleWrite将WaitFor收到的内容打印出来看。然后用字符串处理函数自己处理,截取自己想要的内容。

好了,方法就这些,示例代码也有了。剩下靠自己,有问题再来问~~
 楼主| 发表于 2012-9-11 09:39:54 | 显示全部楼层
好的,我自己在研究琢磨琢磨
不懂再来请教..
我的感觉是跟网络设备打交道又懂得编程的人太少了..
 楼主| 发表于 2012-9-11 09:40:20 | 显示全部楼层
好的,我自己在研究琢磨琢磨
不懂再来请教..
我的感觉是跟网络设备打交道又懂得编程的人太少了..
 楼主| 发表于 2012-9-11 10:21:38 | 显示全部楼层
回复 6# xiehuahere

我按照你的提示写了一段,大致的思路是定义server ,sername,password,然后用init()开始telnet,用sendline发送命令,用waitfor检测返回,用cleanOnExit退出
但是我不明白autoit的函数调用
我把server改成了101.900,明显是不对的,但是我运行总是提示  如果telnet返回不是-1,就关闭tcp连接  
用户名也是错的..还请指导,谢谢
Local Const $username = "fanfang", $password = "123456"
Local $server, $socket = -1
$server = "172.28.101.900";服务器IP
Local $buff = "", $buffSize = 500  ;for receiving ack
  
OnAutoItExitRegister("_CleanOnExit")
  
Func Init()
        TCPStartup()
        $socket = TCPConnect($server, 23) ; 23 - telnet port
        If @error Then Return -1
                                MsgBox(0,"","服务器连接出错")

        
        ; Verify if it's login request
        If WaitFor("login") = -1 Then Return -1
                MsgBox(0,"","没有找到用户名输入点")

        ;Send username
        If SendLine($username) = -1 Then Return -1
                MsgBox(0,"","用户名发送出错")
                
        If WaitFor("password") = -1 Then
                ;Handle the case that password is removed
                If StringInStr($buff, "# ") = 0 Then
                        $needPW = False
                                                MsgBox(0,"","不需要密码")

                           Else
                        Return -1
                                                MsgBox(0,"","没有找到密码输入点")
                                    EndIf
        EndIf
        
        If $needPW Then
                ;Send password
                If SendLine($password) = -1 Then Return -1
                                                MsgBox(0,"","密码发送失败")
                If WaitFor("# ") = -1 Then Return -1        
                                                                MsgBox(0,"","这里是干什么?????????")
        EndIf
        Return 0
                

                
EndFunc
 
 
Global $buff  ; to hold the received content
 $string="ps"
;=================================================================
; Name: SendLine
; Description: Send one command line (@CRLF added automatically)
; Return value: 0 - Success
;         -1 - Failure
;=================================================================
Func SendLine($string)
        TCPSend($socket, $string & @CRLF)
        If @error Then
                ;Local $result = DllCall("Ws2_32.dll", "int", "WSAGetLastError")
                ;Return $result[0]
                 Return -1
        EndIf
        Return 0
EndFunc
  
;=================================================================
; Name: WaitFor
; Description: Wait for desired output. Use it after each TCPSend() to make
;       buff always hold the latest content
; Return value: 0 - Success
;       -1 - Failure
;=================================================================
Func WaitFor($string, $timeout=2000)
        Local $recv = ""
        $buff = ""      
        If $string <> "" Then
                $timer = TimerInit()
                Do
                        $recv &= TCPRecv($socket, $buffSize)
                        If @error <> 0 Then Return -1
                        If $recv == "" Then
                                Sleep(20)
                        Else
                                $buff &= $recv
                        EndIf
                        If TimerDiff($timer) > $timeout Then Return -1
                Until StringInStr($buff, $string) > 0
        EndIf
        Return 0
EndFunc


 
Func _CleanOnExit()
                If $socket <> -1 Then TCPCloseSocket($socket)
        MsgBox(0,"","如果telnet返回不是-1,就关闭tcp连接")
                TCPShutdown()
EndFunc
发表于 2012-9-11 10:42:46 | 显示全部楼层
回复 9# 小熵

没看懂你的问题。。。
server不对,TCPConnect就会出错,会设置@error,Init函数就会返回-1啊
你为什么搞个错误的server和用户名呢?
还有,关于$buff的定义重复了,在文件开头定义,保留上面一个即可。
 楼主| 发表于 2012-9-11 10:45:56 | 显示全部楼层
搞个错误的就是为了测试会不会@error返回-1
我也被搞的非常糊涂了,表示作为一个非编程的人士,autoit的代码还是很难懂
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-27 16:16 , Processed in 0.080750 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表