首页 > 解决方案 > 如何修改此 TCL 客户端/服务器程序以使服务器连续向端口写入数据?

问题描述

我阅读了 fileevent 和 fconfigure 示例,并且能够让 echo 服务器正常工作。我需要一些关于如何修改它的指示,以便每当客户端连接到它时,我可以让服务器每 10 秒写入一次通道。

最终,我希望客户端处理连续的数据流。

服务器:

proc accept {chan addr port} {
   global echo
   puts "connection accepted from $addr:$port"
   set echo(addr,$chan) [list $addr $port]
   fconfigure $chan -buffering line
   fileevent $chan readable [list Echo $chan]
}

proc Echo {sock} {
   global echo

   if {[eof $sock] || [catch {gets $sock line}]} {
      close $sock
      puts "Close $echo(addr,$sock)"
      unset echo(addr,$sock)
   } else {
      puts $sock $line
      puts $line
   }
}

set s [socket -server accept 12345]
vwait forever

此服务器将接受连接并回显客户端写入通道的任何内容。

客户:

set conn [socket localhost 12345]
fconfigure $conn -buffering line
puts $conn "Hello world"

标签: serverclienttcl

解决方案


了解您要实现的协议是正确设置套接字服务器的关键。在您的情况下,如果您每 10 秒编写一次消息并且不监听来自客户端的内容,那么您的代码将变为:

proc accept {chan addr port} {
   global echo
   puts "connection accepted from $addr:$port"
   fconfigure $chan -buffering line
   WriteMessagePeriodically $chan 10000
}

proc WriteMessagePeriodically {chan delay} {
    # Reschedule first to keep timer drift down; we'll cancel if the write fails
    set id [after $delay [list WriteMessagePeriodically $chan $delay]]
    if {[catch {
        puts $chan "This is a message"
        # That will error out if the socket is closed
    }]} {
        after cancel $id
        close $chan
    }
}

当然,如果你使用的是 Tcl 8.6,那么你可以写得更清楚一点:

proc WriteMessagePeriodically {chan delay} {
    # Reschedule first to keep timer drift down; we'll cancel if the write fails
    set id [after $delay [list WriteMessagePeriodically $chan $delay]]
    try {
        puts $chan "This is a message"
        # That will error out if the socket is closed
    } on error {} {
        after cancel $id
        close $chan
    }
}

推荐阅读