Version 29 of comm

Updated 2005-02-08 15:29:55 by hkoba

http://tcllib.sourceforge.net/doc/comm.html


Background: comm is a communication package. It essentially reimplements the send command known from Tk in terms of sockets. The original author is John Robert LoVerso.


Can one use comm as an exact replacement for send? Apparently not - using send, an interpreter registers itself and other Tk applications can query this registry to find out what interpreters are available. If you are just using comm, this is not the case.

EE: Well then, how does an application using comm find out who it can talk to?

AK: There is a little nameserver application at http://www.purl.org/net/akupries/soft/pool/pkg_Pool_Net.html Application have to explicitly register. In that way comm is not as automatic as tk's send.

LV I wonder if someone would be interested in writing a namesever that gets invoke from some sort of comm init function - I don't know how it would work , but surely it would be worth brainstorming.

AK Tk's send is quite simpler, having the X server automatically available as a hub for communication. Ok, back to a comm nameserver. The implementation in pool (s.a.) uses a fixed port number and also implictly assumes that nameserver and applications are on the same host. IOW, local machine. Do we need more flexibility ? If yes, some sort of global configuration file is required so that clients are able to find the server whereever it is and on whatever port it is running.


LV In my mind, the ideal would be to do something similar to send - have comm transparently create an automatic hub for communication. One change I would make is to number the first interp registered as command #1, instead of just command. That might make distinguishing which command is available a bit more regular...

AK Ok, the above implies a fixed port. As for naming the existing code asks for an explicit name and the server will reject it if that name is already registered. ... Automatic generation of a name is a tad more difficult. [info nameofexecutable] is not right, [info script] will give the wrong information too, ... Ok, our best bet is argv0, right ? So that problem is essentially solved too. I believe we are now ready to submit a tcllib FR. (I just added 'comm' as category to the FR tracker of tcllib. It will auto-assign to me).


Anyone able to provide some simple example code showing use of comm?


tkinspect has this example (originally by John LoVerso):

 # Provide non-send based support using tklib's comm package.
 if {![catch {package require comm}]} {
    # defer the cleanup for 2 seconds to allow other events to process
    comm::comm hook lost {after 2000 set x 1; vwait x}

    #
    # replace send with version that does both send and comm
    #
    if [string match send [info command send]] {
        rename send tk_send
    } else {
        proc tk_send args {}
    }
    proc send {app args} {
        if [string match {[0-9]*} [lindex $app 0]] {
            eval comm::comm send [list $app] $args
        } else {
            eval tk_send [list $app] $args
        }
    }
 }

The above enables the use of both comm and send based upon the application id.

PT 23Jun2003: The send page has a somewhat more complete version of the above script.


CMcC Has anyone thought of, or about, or done any work on putting a safetcl safe interpreter (with policies) behind comm?

AK - Thought about it ? Yes, definitely. Done something about it ? No, not yet. I will gladly review patches in this area.

CMcC I've dabbled, and it's becoming necessary for me to do something about it for the persistent itcl stuff. As for the SSL wrapping below, it should be possible to make safe interpretation happen in a callback.

AK Another thing to think about in this context would be the ability to use a different socket command (for example [tls::socket], see TLS). In the case of the example this would add SSL encryption to connections opened by comm.

CMcC It won't be necessary to modify the socket command, as the comm package permits a callback on connect, in which one can wrap SSL around an open socket with tls::import.


LV Has anyone experimented with sending and receiving data to a running Tcl interpreter from a non-Tcl application, making use of comm? Just curious - I've seen C/C++ apps that make use of the C API provided by tclXtSend .


UK I have build something comm-like using udp multicast, channels are differentiated by destination ports. Information is transfered mostly by sending scripts like {array set <arrname <list>} or {set <varname> <value>}. This works across tcl, c and bash ( sending only by echo <script> >/dev/udp/<mcast-ip>/<d-port>. This allows for apps to be restarted or moved from one machine to another and very easy logging and monitoring. but it is unsave at any speed. I will make a wiki page in a couple of days. Look for GIN.


Using comm to remote hosts

When the comm package initialises it creates a self channel by opening a listening socket on the local network interface. That is the 127.0.0.1 interface. If you need to provide for remote access you should use the [comm::comm config] command and set the -local option to false.

On the client side, a remote comm channel is specified as a list where the second element is the hostname. So try using

 comm::comm send [list $portnum $host] info hostname

If you would like to see a remote service ala [winfo interps] you can pre-register the channel using [comm::comm connect $connection]. Then [comm::comm interps] will show this item. [PT]

hkoba - For this purpose, you may feel better with comm via ssh, like this:

  set num [sshcomm::client::create $host]
  comm::comm send $num {glob *}

Alex Caldwell

I used the "Tk appname" command to make this little server that registers the ID of each interpreter registered under the comm package and then broadcasts the name to the other interpreters using Tk appname, so the send command under comm will work the same as under Xwindow using the usual application name as per winfo interps instead of the ID no. I'm sure there are more efficient ways to do this, but it worked on Windows before I discovered the Winsend package. The Winsend package must be doing something like this internally. The main advantage of using the app name instead of an ID no. is you don't have to re-write code that uses the send command on unix when you want to port it to Windows or Mac.

   # each interpreter  needs to have this proc added somewhere 
   proc returnappname {} {
       return [tk appname]
   }

   package require comm
   namespace import ::comm::*

   label .label1 -text "Programs Found"
   pack .label1
   wm title . [comm self]
   for {set x [expr [comm self] - 10]} {$x < [comm self]} {incr x} {
       frame .${x}frame
       entry .${x}frame.entry -textvariable value($x)
       pack .${x}frame -side top
       pack .${x}frame.entry -side left
       update idletasks

       catch {comm send $x returnappname} f
       set value($x) $f
       if ![regexp "to" $value($x)]  {
           pack .${x}frame -side top
           pack .${x}frame.entry -side left
       }
   }
   update idletasks
   button .commbutton -text commsetup -command {
       for {set x [expr [comm self] - 10]} {$x < [comm self]} {incr x} {
           update idletasks
           if {[lindex $value($x) 1] != "to"} {
               puts [lindex $value($x) 0]
               puts [lindex $value($x) 1]
               for {set y [expr [comm self] - 10]} {$y < [comm self]} {incr y} {
                   if {[lindex $value($y) 1] != "to"} {
                       comm send [lindex $value($y) 1] "set [lindex $value($x) 0] [lindex $value($x) 1]"
                       puts "sending [lindex $value($y) 1] set [lindex $value($x) 0] [lindex $value($x) 1]"
                   }
               }
           }
       }
   }
   pack .commbutton
   update idletasks
   after 10000
   .commbutton invoke
   after 10000
   exit

Category Package, subset Tcllib