【问题标题】:Executing command on the server side在服务器端执行命令
【发布时间】:2021-10-28 11:45:47
【问题描述】:

在尝试使用 TCL 运行基于服务器-客户端的功能时,当客户端发送要在服务器端执行的内容时,除了 puts "string" 之外,我无法执行命令 tcl 命令(客户端和服务器都是基于 tcl 的)。我在客户端尝试了如下命令:

puts $channel {set x 1};flush $channel;
puts $channel {incr x}; flush $channel;
puts $channel {puts $x}; flush $channel;

但最后一行没有显示 x 的值,它只是给出一个空行作为输出。在服务器端,我正在使用:

if {[catch {eval $line} $result]} {puts $result }

有人能说明为什么 x 没有被评估和打印吗?另外,如何为从客户端发送到服务器或反之亦然的变量定义范围?

【问题讨论】:

    标签: sockets server client tcl


    【解决方案1】:

    catch 命令的第三个参数应该是一个变量name。您使用了 result 变量的 ,它显然是空的,因为您报告该命令会生成一个空行作为输出。

    所以你至少要省略美元符号:

    if {[catch {eval $line} result]} {puts $result}
    

    但鉴于 catch 将评估其第二个参数,这有点令人费解。可以简化为:

    if {[catch $line result]} {puts $result}
    

    当您处理 proc 内的套接字数据(您从例如文件事件调用)时,范围将是该 proc。所以每次你都会得到一个(几乎)空白的范围。在 proc 的不同调用中运行的早期命令的效果将丢失。这就是为什么puts $x 可能会因can't read "x": no such variable 而失败。

    您可以使用以下命令在全局范围内运行接收到的命令:

    if {[catch {uplevel #0 $line} result]} {puts $result}
    

    在单独的(安全的)解释器中运行它们可能会更好:

    # In your initialization code (running once):
    interp create rje
    
    # In your file event handler:
    if {[catch {rje eval $line} result]} {puts $result}
    

    使用安全解释器时,它不会自动访问“stdout”通道。您必须按以下方式安排:

    # In your initialization code (running once):
    interp create -safe rje
    interp share {} stdout rje
    
    # In your file event handler:
    if {[catch {rje eval $line} result]} {puts $result}
    

    【讨论】:

    • 对于不熟悉旧 UNIX 系统的人:每个帐户过去都有一个用于“远程作业条目”的目录,称为“rje”。在这种情况下,这似乎也是解释器的合适名称。
    • 感谢您的回答。我现在可以使用 uplevel 增加 x 的值。安全口译员的优势是什么?为什么推荐它?
    • 使用解释器将用于执行远程命令的环境与您的代码完全隔离,因此远程命令将无法覆盖您的变量和过程。安全的解释器将确保远程命令不会对您的系统造成任何破坏。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    • 2012-05-24
    • 2013-03-15
    • 2022-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多