当我向python发送“无效命令”时,TCL客户端挂起

2024-10-04 07:35:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我的设置中有一个python服务器和一个TCL客户机,它们都运行在同一台机器上,使用端口8020。在

我基本上在python服务器中实现了一些函数来执行一些操作。在

我正在尝试在python服务器中添加一些异常处理,特别是当TCL客户机试图调用python中尚不可用的函数时。python服务器应该提醒TCL客户机该功能还不可用。在

我已经复制粘贴了我的代码以下:在

PYTHON服务器代码

import socket
import sys
import os

DUT_Browser = ""
host = 'localhost'
port = 8020
print 'Current working Directory:',os.getcwd()


def LogError(message):
    try:
        logfile = open("log.txt", "a")
        try:
            logfile.write(message)
        finally:
            logfile.close()
    except IOError:
        pass

def GetParam(sParams, i):
    params = sParams.split(",")
    p = params[i].strip()
    p = p.strip("\"")

    return p

def Login(sParams):
    print "In method Login with parameters:", sParams

    return 0


def ExecuteKeyword(sCommand):
    vals = sCommand.partition("(")
    sKeyword = vals[0].strip()
    sParams = vals[2].strip()
    # Remove the trailing ")" from the parameters string
    sParams = sParams[:-1]
    #print "KEYWORD: ", sKeyword, "PARAMETERS: ", sParams
    func = getattr(sys.modules[__name__],sKeyword)
    failed = 1
    failed=func(sParams)
    if failed:
        return 1
    else:
        return 0

def clientthread(conn):
    while True:
        keyword = conn.recv(1024)
        errorMsg = 'none'
        failed = 1
        try:
           failed=ExecuteKeyword(keyword)
        except (Exception, FindFailed), err:
        #except Exception, err:
            errorMsg=str(err)
            LogError(errorMsg)
        if failed:
            reply = 'FAIL START' + errorMsg + 'FAIL END'
            print 'ERROR MSG:',reply
        else:
            reply = 'PASS: ' + keyword
        if not keyword:
           break
        print 'SERVER REPLY',reply
        conn.sendall(reply)
        print 'SERVER REPLY SENT'
    conn.close()

sdServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'TCP (SOCK_STREAM) Socket created'

try:
    sdServer.bind((host, port))
except socket.error , msg:
    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
    sys.exit()

print 'Socket bind to port:',port,'on host:',host,'is complete'

#Start listening on socket
sdServer.listen(10)
print 'Socket now listening for 10 connections'
while 1:
    #wait to accept a connection - blocking call
    conn, addr = sdServer.accept()
    print 'Connected with ' + addr[0] + ':' + str(addr[1])
    #try:
    clientthread(conn)
    #except socket.error , err:
    #    print str(err)

sdServer.close()

TCL客户端代码

^{pr2}$

当我从客户机输入以下命令时,它将按预期传递和行为 并打印来自服务器的消息。在

Login("10.218.164.58",admin,admin,\"FALSE\")

但是,当我使用以下命令时,客户机还没有实现 挂起并且不从服务器打印异常,表明它尚未实现。在

Logout("10.218.164.58")

我甚至尝试使用wireshark,发现服务器确实发出了消息,TCL客户端似乎也发出了ACK作为响应。所以不太清楚为什么“得到”应该挂起来。在


Tags: 服务器host客户机defsocketconnreplytcl
1条回答
网友
1楼 · 发布于 2024-10-04 07:35:16

我不太确定出了什么问题,但我怀疑问题出在Tcl代码中。可能有很多问题(是否有一个新行被传回?)但关键的是代码实际上并不是特别惯用。下面是一个更惯用的版本:

set port 8020
set host localhost
set sdClient [socket $host $port]
fconfigure $sdClient -buffering line
while true {
    puts "Enter some command for $sdClient"
    gets stdin ntoGuiCmd
    if {[eof stdin] || $ntoGuiCmd eq "end"} {
        break
    }
    if {[catch {puts $sdClient $ntoGuiCmd}]} {
        break
    }
    ### Replacement discussed below starts here
    gets $sdClient serverMessage
    if {[eof $sdClient]} {
        break
    }
    puts "From Server: $serverMessage"
    # If multiline messages are possible, extra work is required here!
    ### Replacement ends here
}
close $sdClient

如果你有多行响应,你需要更加小心。最好的方法是读取它们,直到您知道已经到达响应的末尾(例如,因为服务器告诉您字节数或行数),但这并不总是可能的。如果您假设总是将响应放在单个数据包中,那么您可以使用它来读取可用的行(当存在未读字节时,它以非阻塞模式从套接字读取数据):

^{pr2}$

如果一个响应足够大(这取决于操作系统缓冲区等),那么它将不会被写入一个包中。这时你真的需要在你的消息传递协议中有一个明确的标记,表明响应的结束在哪里。(反过来也是一样,只是大请求会导致问题。)


如果这都是我自己的代码,我很想做一个完全异步的非阻塞客户机:

proc transfer {from to} {
    if {[gets $from line] >= 0} {
        puts $to $line
    } elseif {[eof $from]} {
        exit
    }
}

set sock [socket "localhost" 8020]
fconfigure stdin -blocking 0
fconfigure $sock -blocking 0
fileevent stdin readable [list transfer stdin $sock]
fileevent $sock readable [list transfer $sock stdout]
vwait forever

然而,这是一种非常不同的客户机风格(而且不容易包装到前端API中)。在

相关问题 更多 >