写入前检查异常掉线

Check abnormal connection drop before writing

我是 TCL 脚本和编写生产代码以打开到我们服务器的套接字并编写命令然后读取其输出的新手。下面是我的代码:

set chan [socket 123.345.45.33 23]
fconfigure $chan -buffering line
foreach item [dict keys $command] { 
    set cmd [dict get $command $item]
    set res [Data_write $chan "get data $cmd"]  
}

其中 Data_write 程序如下所述:

proc Data_write { channel data } {
    if {[eof $channel]} {
        close $channel
        ST_puts "Data_write: Error while writing to chanel"
        return -1
    } else {
        puts $channel $data
        return 0
    }
}

我不确定我们如何才能实现以下验证:

  1. set chan [socket 123.345.45.33 23] - socket connection open is success
  2. fconfigure on the channel is success
  3. How to know before any write that any abnormal connection drop has happen on channel?

利用socket -async和可读可写的fileevents使整个连接过程事件化

在可写事件中,您可以使用fconfigure $channel -error检查连接状态。如果连接失败,套接字变为可写,并且错误条件出现在错误 属性 上。如果这是空的,那么您可以配置可读事件并开始处理来自套接字的数据。在任何可读事件处理程序中,您应该在读取后检查 eof 并禁用可读事件处理程序,或者一旦 eof 被视为处于 eof 状态的套接字变得持续可读,则关闭套接字。

粗略计算如下:

proc OnWritable {chan} {
   set err [fconfigure $chan -error]
   if {$err ne "" } {
       puts stderr "ERROR: $err"
       exit 1
   }
   fconfigure $chan -blocking 0 -buffering none -encoding binary -translation lf
   fileevent $chan writable {}
   fileevent $chan readable [list OnReadable $chan]
}

proc OnReadable {chan} {
    set data [read $chan]
    puts "[string length $data]: $data"
    if {[eof $chan]} {
        fileevent $chan readable {}
        puts "closed $chan"
        set ::forever "closed"
    }
}

set sock [socket -async $address $port]
fileevent $sock writable [list OnWriteable $sock]
vwait ::forever
  1. set chan [socket 123.345.45.33 23] - socket connection open is success
  2. fconfigure on the channel is success

这些很简单:如果出现故障,您将收到 Tcl 错误,这是一种异常。如果需要,可以使用 catchtry 来捕获错误:

try {
    set chan [socket 123.345.45.33 23]
    fconfigure $chan -buffering line
} on error msg {
    puts "a serious problem happened: $msg"
    # Maybe also exit here...
}
  1. How to know before any write that any abnormal connection drop has happen on channel?

坏消息是您无法知道这一点。 OS 本身不会真正知道这一点,除非您执行以下两件事之一:写入通道,或从通道读取。 (有 有时 可用的提示,例如 fileevent 事件触发,但它们根本不确定。)相反,您需要在实际执行时捕获错误写。一般模式见上文。

记住:Tcl 操作失败时会抛出错误,EOF 在读取时不是错误,但在写入时是错误。