首页 > 解决方案 > 在服务器端执行命令

问题描述

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

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 没有被评估和打印吗?此外,如何为从客户端发送到服务器的变量定义范围,反之亦然?

标签: socketsserverclienttcl

解决方案


catch 命令的第三个参数应该是一个变量。您使用了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}

推荐阅读