Sockets 使用TCL插座时的挂窗
我正在使用tclsocket命令在两个TCL/Tk应用程序(比如A和B)之间进行通信,这两个应用程序都有一个相关的GUI。B上的服务器基本上接受A的命令并返回执行结果。问题是B的GUI在执行完成后立即挂起。有没有办法让两个GUI独立工作?我正在使用以下脚本设置两个应用程序之间的连接: 使用以下TCL脚本client.TCL启动应用程序ASockets 使用TCL插座时的挂窗,sockets,tcl,tk,Sockets,Tcl,Tk,我正在使用tclsocket命令在两个TCL/Tk应用程序(比如A和B)之间进行通信,这两个应用程序都有一个相关的GUI。B上的服务器基本上接受A的命令并返回执行结果。问题是B的GUI在执行完成后立即挂起。有没有办法让两个GUI独立工作?我正在使用以下脚本设置两个应用程序之间的连接: 使用以下TCL脚本client.TCL启动应用程序A proc execute { cmd } { set cid [socket localhost 9900] puts $cid $cmd
proc execute { cmd } {
set cid [socket localhost 9900]
puts $cid $cmd
while { [gets $cid line] >= 0 } {
puts $line
}
close $cid
}
set pid [exec B server.tcl &]
execute {puts HelloWorld}
其中server.tcl通过应用程序B设置服务器
proc server { cid addr port } {
set cmd [gets $cid]
catch $cmd result
puts $cid result
close $cid
}
socket -server server 9900
vwait forever
目标是让B的GUI处于活动状态,同时用户继续使用A的GUI。这样,用户可以根据需要在两个GUI之间切换。A和B都提供不同的功能来处理需要同时提供的相同数据。您发布的代码有两个关键问题:
fileevent
注册的脚本以非阻塞模式处理接受的套接字fconfigure $cid -buffering none
打开插座后立即打开。这告诉Tcl,它应该始终将您放入的数据立即发送到套接字上的通道。(或者,使用line
而不是none
来获得行缓冲;这在这种情况下也可以很好地工作。)您还可以执行显式刷新:
flush $cid
这将在放置之后进行
关键问题2
最佳实践将使用更像这样的服务器脚本,一个过程用于设置接受的套接字连接的服务,另一个过程用于处理消息的读写。accept过程(server
)关闭阻塞(并经常调整缓冲),操作过程(readLine
)使用eof
和fblocked
计算是成功还是失败
proc server { cid addr port } {
fconfigure $cid -blocking 0
fileevent $cid readable "readLine $cid"
}
proc readLine { cid } {
set cmd [gets $cid]
if { [eof $cid] } {
close $cid
} elseif { ![fblocked $cid] } {
catch $cmd result
puts $cid $result
close $cid
}
}
socket -server server 9900
vwait forever
另一个问题
如果你真的这么做,另一个大问题是多行消息很有用。您需要将readLine
设置为上面的累加行,直到它有一个完整的命令(append
和info complete
帮助),或者您需要一些其他机制来处理数据传输。在生产代码中,委托给comm之类的包变得更容易。是的,有一种方法;事实上,有几种方法。您必须提供更多关于B正在做什么的信息,以便我们能够提供帮助。如果您以前从未编写过异步程序,那么您将不得不学习:从一开始就可能会让您的大脑弯曲。@DonalFellows我已经添加了更多关于我要做什么的信息。如果你还需要什么,请告诉我。在此期间,我将尝试深入研究异步程序。Donal在尝试了更多的东西后,我发现当我对客户端和服务器都使用wish时,它们可以独立工作。看起来问题出在我和wish一起使用的程序上。我不知道怎么才能找到问题。此外,服务器仍然工作正常,我可以恢复命令输出。只有GUI没有响应。我自己在服务器上的小愿望小部件似乎工作正常。谢谢你的帮助。Donal,在这种情况下,使用open运行程序似乎很有效。我能够向程序发送命令,并在程序B在后台运行时返回结果。这是一个正确的方法吗?看看tcllib comm包,特别是异步部分,它可能会做你想要的。谢谢你详细的回答,多纳尔。我将合并您建议的更改。要添加此更改,您需要告诉Tcl使用“vwait-forever”Tcl命令“挂起”。它正是这样做的——永远地等待,或者用简单的英语说,看起来像是在等待。您需要包含某种代码,以便在服务器完成后正常关闭。如果只处理一个请求,然后关闭,请在“close$cid”之后添加一个“exit”,它将退出程序并返回操作系统。