While trying to run a server-client based functionality using TCL, i am unable to execute the command tcl commands other than puts "string" when the client sends something to execute on the server side (both client and server are tcl based). I tried commands as below on the client:
puts $channel {set x 1};flush $channel;
puts $channel {incr x}; flush $channel;
puts $channel {puts $x}; flush $channel;
But the last line doesn't show the value of x, it just gives a blank line as an output. On the server side, i am using:
if {[catch {eval $line} $result]} {puts $result }
Can someone suggest why x is not being evaluated and printed? Also, how does scope is defined for variables sent from client to server or vise versa?
The third argument of the catch command is supposed to be a variable name. You used the value of the result variable, which apparently is empty, given that you report that the command produces a blank line as an output.
So you have to at least omit the dollar sign:
if {[catch {eval $line} result]} {puts $result}
But given that catch will evaluate its second argument, that's a bit convoluted. It can be simplified to:
if {[catch $line result]} {puts $result}
When you handle the socket data inside a proc (that you invoke from e.g. a file event), the scope will be that proc. So every time you will get a (nearly) blank scope. The effects of the earlier commands that ran in a different invocation of the proc will have been lost. That's why the puts $x
is likely to fail with can't read "x": no such variable
.
You can run the received commands in the global scope using:
if {[catch {uplevel #0 $line} result]} {puts $result}
It is likely even better to run them in a separate (safe) interpreter:
# In your initialization code (running once):
interp create rje
# In your file event handler:
if {[catch {rje eval $line} result]} {puts $result}
When using a safe interpreter, it doesn't automatically have access to the "stdout" channel. You will have to arrange for that as follows:
# 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}