Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Getting working code to work with socket communications

10 views
Skip to first unread message

mhnpit...@gmail.com

unread,
Aug 21, 2007, 10:42:06 AM8/21/07
to
Hello,
I have dozens of small computers with large tcl processes running on
them. To suite legacy code, I must communicate to them by doing a
telnet to a certain port of the machine in question, call it 'port'
for convenience. In short, I need to be able to
telnet ip_address port
and have the tcl program recognize that something attempted to telnet
to the port, have the "recognition routine" set some sort of global
variable, call it "do_the_action", and then have the legacy code check
for the said global variable, and take an action if it is set.

I have a template program pasted further below, mostely taken from the
web. It seems to *almost* work. The communication part works, but
the code never gets to the real working code. Though simulated by a
simple loop, in actual practice the real working code is over a
hundred thousand lines spread accross many .tcl files.

How do I get the working code to work as normal and yet have the
communications set up? I have tried all sorts of arrangements, with
and without the vwait.

# ---------------------paste example
# Run this in one window, say, on the_host,
# In another window,
# telnet the_host 9900
# The result will show
# Connection from the_host registered
# every time 'telnet the_host 9900' is done.
#

global do_the_action
set do_the_action 0

proc Server {channel clientaddr clientport} {
puts "Connection from $clientaddr registered"
puts $channel [clock format [clock seconds]]
close $channel
set do_the_action 1
}

socket -server Server 9900

vwait forever

# And here is the corresponding client to talk to the server:

set server localhost
set sockChan [socket $server -myaddr 9900]

gets $sockChan line
close $sockChan
puts "The time on $server is $line"

# Unfortuantely, the code execution never gets past here. This
# simulates the real, working section of the code, and is in reality
# well over a hundred thousand lines long.

for {set x 0} {$x<10} {incr x} {
puts "x is $x"
after 1000
if { $do_the_action } { break; }
}

#--------------------- end paste example

John Seal

unread,
Aug 21, 2007, 11:08:43 AM8/21/07
to
mhnpit...@gmail.com wrote:
> # ---------------------paste example
> # Run this in one window, say, on the_host,
> # In another window,
> # telnet the_host 9900
> # The result will show
> # Connection from the_host registered
> # every time 'telnet the_host 9900' is done.
> #
>
> global do_the_action
> set do_the_action 0
>
> proc Server {channel clientaddr clientport} {
> puts "Connection from $clientaddr registered"
> puts $channel [clock format [clock seconds]]
> close $channel
> set do_the_action 1
> }
>
> socket -server Server 9900
>
> vwait forever

This is mostly OK. The global declaration needs to be moved inside the
Server proc, as the way the program is written "set do_the_action 0" is
setting a global variable and "set do_the_action 1" is setting a
different local variable.

> # And here is the corresponding client to talk to the server:
>
> set server localhost
> set sockChan [socket $server -myaddr 9900]
>
> gets $sockChan line
> close $sockChan
> puts "The time on $server is $line"
>
> # Unfortuantely, the code execution never gets past here. This
> # simulates the real, working section of the code, and is in reality
> # well over a hundred thousand lines long.
>
> for {set x 0} {$x<10} {incr x} {
> puts "x is $x"
> after 1000
> if { $do_the_action } { break; }
> }

The syntax for [socket $server -myaddr 9900] should be [socket $server
9900]. If I make that change, then execution *does* get to your sample
code, but it errors out because there's no such variable as
do_the_action on the client end... it can't magically tunnel through the
socket to see the one on the server end (which is always 0 anyway).

mhnpit...@gmail.com

unread,
Aug 21, 2007, 12:17:10 PM8/21/07
to
I added
global do_the_action
to the proc Server. The "for" statement still does not get executed.

Are you seeing the printouts for the values of x?

mhnpit...@gmail.com

unread,
Aug 21, 2007, 12:30:25 PM8/21/07
to
In the example below, the goal is to have
puts "x is $x"
executed UNTIL 'telnet the_host 9900' is done.
Instead, the puts statement is not execute UNLESS

'telnet the_host 9900' is done.

# ---------------------paste example
# Run this in one window, say, on the_host,
# In another window,
#

# The result will show
# Connection from the_host registered
# every time 'telnet the_host 9900' is done.
#
global do_the_action
set do_the_action 0


proc Server {channel clientaddr clientport} {

global do_the_action

puts "Connection from $clientaddr registered"

puts "10: do_the_action is $do_the_action"
close $channel

set do_the_action 1

}

socket -server Server 9900

vwait do_the_action
puts "20: do_the_action is $do_the_action"

# Unfortnately, the code execution never gets past here. This


# simulates the real, working section of the code, and is in reality
# well over a hundred thousand lines long.

for {set x 0} {$x<10} {incr x} {
puts "x is $x"
after 1000
if { $do_the_action } { break; }
}

#--------------------- end paste example

sleb...@gmail.com

unread,
Aug 21, 2007, 8:26:27 PM8/21/07
to
On Aug 22, 12:30 am, mhnpittsbu...@gmail.com wrote:
> In the example below, the goal is to have
> puts "x is $x"
> executed UNTIL 'telnet the_host 9900' is done.
> Instead, the puts statement is not execute UNLESS
> 'telnet the_host 9900' is done.
> <snip>
>
> vwait do_the_action
>

The vwait line above means "stop here until the variable do_the_action
is written to". Hence the following for loop is not executed UNLESS
$do_the_action is modified.

To get the effect you want I'd suggest using the event loop by
exploiting [after]:

# global do_the_action <-- this is meaningless
set do_the_action 0

proc Server {channel clientaddr clientport} {
global do_the_action

puts "Connection from $clientaddr registered"
puts "10: do_the_action is $do_the_action"
close $channel

set do_the_action 1
}

socket -server Server 9900

puts "20: do_the_action is $do_the_action"

proc loop {x} {
global do_the_action

puts "x is $x"
incr x

if { $do_the_action } { break; }
after 1000 "loop $x"
}
loop

vwait do_the_action
# for event driven code, vwait should
# always be the last line.

mhnpit...@gmail.com

unread,
Aug 22, 2007, 8:19:27 AM8/22/07
to
It works! Thanks

Cameron Laird

unread,
Aug 22, 2007, 9:27:16 AM8/22/07
to
In article <1187785167.7...@x40g2000prg.googlegroups.com>,
<mhnpit...@gmail.com> wrote:
>It works! Thanks
>

It's rewarding to know that this was successful. Thanks for
taking the trouble to confirm explicitly your satisfaction.

I think this problem deserves a summary I don't know how to put
into words. Fine-grained programmatic remote control of hundreds
of distributed hosts--well, it's a challenge I've seen stump
practitioners with many other languages. The Tcl solution worked
out here is, in contrast, so readable that a beginner can under-
stand it, in my judgment. I wish I knew better how to advertise
such achievements.

0 new messages