0
votes

how does one open a channel that is not a filename in tcl? I've read the docs but I'm not a programmer so I must not understand the open and chan commands because when I try to open a new custom channel

open customchannel1 RDWR

I get errors such as

couldn't execute "customchannel1": no such file or directory

And I'm fully aware that I don't do this correctly:

chan create read customchannel1

invalid command name "customchannel1" ...and... invalid command name "initialize"

All I want is two tcl scripts to be able to talk to each other. I thought I could use channels to do this.

I have, however, successfully created a socket test version of what I want:

proc accept {chan addr port} {
    puts "$addr:$port says [gets $chan]" 
    puts $chan goodbye                   
    close $chan                          
}                                        

puts -nonewline "master or slave? "
flush stdout
set name [gets stdin]

if {$name eq "master"} {
  puts -nonewline "Whats the port? "
  flush stdout
  set port [gets stdin]
  socket -server accept $port
  vwait forever
} else {
  puts "slave then."
  puts -nonewline "Whats the id? "
  flush stdout
  set myid [gets stdin]
  set chan [socket 127.0.0.1 $myid]
  puts $chan hello
  flush $chan
  puts "127.0.0.1:$myid says [gets $chan]"
  close $chan
}

In the above example I can run 3 instances of the program: 2 'masters' with different port numbers, and a 'slave' that can talk to either one depending on the port/'id' it chooses.

If I knew how to open a channel with the open command instead of the socket command I could implement the above code without using sockets, or jimmy-rigging the ports to be used as uniq ids, but every example I can find opens files and writes out to files or standard out which you don't have to create in the first place.

Thanks for helping me understand these concepts and how to implement them better!

2
I'd stick with the socket. You might want to investigate using FIFOs, or the tcl::chan::* modules in tcllib - glenn jackman

2 Answers

2
votes

A channel is simply a high level method for working with already open files or sockets.

From the manual page:

This command provides several operations for reading from, writing to and otherwise manipulating open channels (such as have been created with the open and socket commands, or the default named channels stdin, stdout or stderr which correspond to the process's standard input, output and error streams respectively).

So what you are doing with sockets is correct. You can use the chan command to configure the open socket.

1
votes

When connecting two scripts together, you might think in terms of using a pipeline. For example, you could run one script as a subordinate process of the other. The master does this:

set pipe [open |[list [info nameofexecutable] $thescriptfile] "r+"]

to get a bidirectional (because r+) pipeline to talk to the child, which can in turn just use stdout and stdin as normal.

Within a process, chan pipe is available, which returns a pair of channels that are connected by an OS anonymous pipe.


When working with these, it really helps if you remember to use fconfigure to turn -buffering to none. Otherwise you can get deadlocks while output to a pipe sits in a buffer somewhere, which you don't want. The ultimate answer to that is to use Expect, which uses Unix ptys instead of pipes, but you can be quite productive provided you remember to tune the buffering.