我是否需要在TCL中使用Threads作为我的应用程序?

Pee*_*hpd 2 sockets multithreading tcl

我正在尝试构建的应用程序如下.

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中使用Threads.我打算将ABC.tcl作为一个单独的线程调用,然后让它等待回复.这样Server.tcl可以与ABC.tcl分开执行.

通缉意见是他们有更好的方法吗?如果Threads是唯一更好的方法,我可能遇到的挑战是什么,我该如何处理它们?

编辑:

我没有在Server.tcl和ABC.tcl之间使用套接字通信.在Server.tcl中,我正在寻找ABC.tcl,当一些通信请求来自Java客户端时,我正在调用ABC.tcl的一个过程(比如proc someProc {}).现在在someProc过程中,完成了一些处理,并通过Server.tcl将问题(例如"你想继续吗?")发送回Java客户端.现在在ABC.tcl我希望程序someProc等到用户输入内容.当用户输入答案(是/否)时,我希望程序从等待用户输入的位置继续执行.

现在发生的事情是我无法按要求正确设置等待条件.我尝试使用一个标志变量,当用户输入答案时将更新该标志变量,并尝试根据标志变量在someProc中保持繁忙的等待循环.但是当用户输入到来时,它不会从等待循环开始继续执行.它像普通请求一样启动,进入Server.tcl中注册的过程来处理传入的数据.

我有"vwait事件"调用,并且我在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
Run Code Online (Sandbox Code Playgroud)

标题## serverTest.tcl(As 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"
}
Run Code Online (Sandbox Code Playgroud)

标题##代码中的挑战

我发送一个新请求为"exec:Hello"我发送回复为"回复:是"

正如您在proc svcHandler {}中看到的,如果它是一个新请求,我执行executeCommand {} proc.否则,我设置了replyReady标志.当我执行executeCommand {} proc时,调用proc runServerTest {},它位于serverTest.tcl中.现在在这个过程中,我将问题发回给用户,我可以在客户端的JAVA UI屏幕上看到.当我尝试发送回复时,svcHandler {}中的proc setReplyready {}根本不执行.当我看到日志文件时,我可以看到proc getReplyReadyStatus {}的输出,它在proc runServerTest {}中从while循环调用,每秒一次.这意味着while循环无限期地执行.并且由于没有从svcHandler {}调用proc setReplyReady {},因此while循环不会退出.真的不知道这个过程在哪里等待.任何解决方法?

谢谢,Peeyush

sle*_*man 6

不要使用线程.使用事件循环.

阅读fileevent:http://www.tcl.tk/man/tcl8.6/TclCmd/fileevent.htm

通常,您为Java客户端套接字和ABC脚本套接字设置事件处理程序,以便在它们可读时触发,并在数据到达时执行您需要执行的操作.

如果需要实现定时操作,例如看门狗定时器,请查看after命令.