我正在尝试构建的应用程序如下。
Java 客户端 <---> TCL 服务器(比如 Server.tcl)<---> 其他一些 TCL 脚本(比如 ABC.tcl)
我正在使用 Socket 编程进行 Java Client 和 TCL 服务器之间的通信。现在我的要求是在运行时从 Server.tcl 调用 ABC.tcl。ABC.tcl 在执行时会通过 server.tcl 向 Java 客户端发送一些问题。坐在 Java 客户端的用户应发送对所提问题的答复,并且答复应返回到 ABC.tcl。现在,当回复回来时,ABC.tcl 应该等待。但是我不能在 ABC.tcl 中有一个繁忙的等待循环,因为控制权不会到达 Server.tcl,因为它是与 Java 客户端对话的人。
ABC.tcl 将使用Server.tcl 中定义的一些程序。如果需要,可以更改设计。
我正在考虑在 TCL 中使用线程。我打算将 ABC.tcl 作为一个单独的线程调用,然后让它等待回复。这样,Server.tcl 可以与 ABC.tcl 分开执行。
想要对他们有更好的方法提出意见吗?如果线程是唯一更好的方法,我可能会遇到哪些挑战,我该如何应对?
编辑:
我没有在 Server.tcl 和 ABC.tcl 之间使用套接字通信。在 Server.tcl 中,我正在采购 ABC.tcl,当一些通信请求来自 Java 客户端时,我正在调用 ABC.tcl 的过程(比如 proc someProc{})。现在在 someProc 过程中,完成了一些处理,并通过 Server.tcl 将问题(比如“你想继续吗?”)发送回 Java 客户端。现在在 ABC.tcl 我希望过程 someProc 等到用户输入一些东西。当用户输入答案(是/否)时,我希望程序从等待用户输入的位置继续执行。
现在发生的事情是我无法根据需要正确设置等待条件。我尝试使用将在用户输入答案时更新的标志变量,并尝试根据标志变量在 someProc 中保持繁忙的等待循环。但是当用户输入到来时,它不会从等待循环开始恢复执行。它像正常请求一样开始并进入在 Server.tcl 中注册的过程以处理传入的数据。
我有“vwait events”调用,并且在 Server.tcl 中有“fileevent $sock readable [list svcHandler $sock]”。
我无法得到,我该如何在 ABC.tcl 中的过程 someProc 中等待,并根据用户输入从相同的繁忙等待中恢复处理。
标题 ##Server.tcl 文件:
source "<path>/serverTest.tcl"
set svcPort [lindex $argv 0]
set filePath <path where all related files are kept>
set replyReady 0
set packet ""
proc writeToFile {fileName data mode} {
set fileId [open $fileName $mode]
puts -nonewline $fileId $data
close $fileId
}
proc writeJavaUTF {sock msg} {
set date [exec date]
set msg $date$msg
set data [encoding convertto utf-8 $msg]
puts -nonewline $sock [binary format "S" [string length $data]]$data
}
proc readJavaUTF {sock} {
binary scan [read $sock 2] "S" len
set data [read $sock [expr {$len & 0xFFFF}]]
return [encoding convertfrom utf-8 $data]
}
proc sendMessageToUser {sock msg} {
writeToFile [exec pwd]/CTS/log "\nSending Message Back to Client" "a"
writeJavaUTF $sock $msg\n
}
proc setReplyReady {} {
global replyReady
set replyReady 1
writeToFile [exec pwd]/CTS/log "\nSetReplyReady" "a"
}
proc resetReplyReady {} {
global replyReady
set replyReady 0
writeToFile [exec pwd]/CTS/log "\nResetReplyReady" "a"
}
proc getReplyReadyStatus {} {
global replyReady
writeToFile [exec pwd]/CTS/log "\nReply Ready is : $replyReady" "a"
return $replyReady
}
proc executeCommand {sock msg} {
writeToFile [exec pwd]/CTS/log "\nexecuteCommand" "a"
runServerTest $sock
}
# Handles the input from the client and client shutdown
proc svcHandler {sock} {
global packet replyReady
set packet [readJavaUTF $sock] ;# get the client packet
writeToFile [exec pwd]/CTS/log "\nThe packet from the client is $packet" "w"
set packet [string range $packet 0 [expr {[string first "\n" $packet] - 1}]]
set endChar "EOC"
if {[eof $sock] || ![string compare -nocase $packet $endChar]} { ;# client gone or finished
writeToFile [exec pwd]/CTS/log "Closing the socket" "a"
writeToFile [exec pwd]/CTS/flag "0" "w"
close $sock ;# release the servers client channel
exit
} else {
#doService $sock $ipacket
set typeReply "reply"
set typeExecute "exec"
set type [string range $packet 0 [expr {[string first ":" $packet] - 1}]]
writeToFile [exec pwd]/CTS/log "\nThe type is : $type" "a"
# If it is not a reply for a request
if {![string compare -nocase $type $typeExecute]} {
executeCommand $sock $packet
} else {
writeToFile [exec pwd]/CTS/log "\nExecuting the ELSE" "a"
setReplyReady
}
}
}
proc accept {sock addr port} {
# Setup handler for future communication on client socket
fileevent $sock readable [list svcHandler $sock]
# Read client input in lines, disable blocking I/O
fconfigure $sock -buffering line -blocking 0 -translation binary
return $sock
}
set sock [socket -server accept $svcPort]
vwait events ;# handle events till variable events is set
标题 ## serverTest.tcl(作为 ABC.tcl)
proc runServerTest {sock} {
global replyReady
writeToFile [exec pwd]/CTS/log "\nInside serverTest.tcl." "a"
resetReplyReady
sendMessageToUser $sock "From Server : The socket is working. Do you want to continue ?"
writeToFile [exec pwd]/CTS/log "\nWaiting for user input" "a"
#Loop untill the reply is read from the socket
while {![getReplyReadyStatus]} {
after 1000
}
set retMessage [getPacket]
resetReplyReady
writeToFile [exec pwd]/CTS/log "\nThe reply from user is : $retMessage" "a"
}
标题##代码中的挑战
我以“exec:Hello”的形式发送一个新请求,并以“reply:yes”的形式发送回复
正如您在 proc svcHandler{} 中看到的,如果它是一个新请求,我将执行 executeCommand{} proc。否则,我设置了replyReady 标志。当我执行 executeCommand{} proc 时,调用了 serverTest.tcl 中的 proc runServerTest{}。现在在这个过程中,我将问题发回给用户,我可以在客户端的 JAVA UI 屏幕上看到它。当我尝试发送回复时,svcHandler{} 中的 proc setReplyready{} 根本不会执行。当我看到日志文件时,我可以看到 proc getReplyReadyStatus{} 的输出,该输出每秒被 proc runServerTest{} 中的 while 循环调用。这意味着 while 循环无限期地执行。并且由于没有从 svcHandler{} 调用 proc setReplyReady{} 可能是 while 循环没有退出。真的不知道进程在哪里等待。任何解决方法?
谢谢, Peeyush