February, 2012
The MSG protocol is based on messages exchanged over TCP/IP sockets and can probably be implemented by virtually any modern programming language. The most widely used MSG library is the Tcl library, although a full featured C language library was developed by SAO.
An MSG server publishes variables and registers commands. Clients may execute commands, and set, get, or subscribe to variables. An "lst" command is provided to allow a client to ask a server to enumerate the full set of variables and commands it provides.
A unique part of the protocol is the subscription facility, which allows a client to subscribe to a server for a specific variable. Once this is done, the server will notify the client whenever the value of a variable changes. This kind of asynchronous notification can be tricky to program. A simple client can ignore this facility and simply set or get variables.
A message from a client looks like this:
num command args\nThe num value is non-zero if an ACK is requested, 0 if it should be suppressed. If an ACK is requested, the num value is sent with the ACK. A get command with num=0 is pointless as nothing will be returned. There are 4 builtin commands: set, get, lst, and subscribe All commands end with a newline character.
7 get flag 7 ack 99
Commands exist to setup a server, publish variables, register commands, and to restrict which clients can access a server, but are not discussed in detail here.
The following Tcl code will set up a simple msg server:
#package require msg source msg.tcl set local_state bogus set server XYZ set env($server) .:3999 msg_server $server msg_allow "*" msg_publish $server state local_state msg_up $server vwait foreverNote first of all the little dance with the env array. You decide on a name for your server (by tradition with all capitals), then set the value of this name in the env array to be the host:port string you would like it to use. What a script could do is to check if this value was already set and if so leave it alone to be discovered by msg initialization. Or you can just ignore the env array entirely, and pass the host:port string as a second argument to msg_server like so:
msg_server $server .:3999
In any event, you pass your server name as the first argument to each and every msg routine you call.
Invisibly to you (hopefully) the msg library creates a global array with the same name as your server (XYZ in the example above) and uses this for working storage. You should never care about the following, but in one example I studied (with server name "TT") , the following 21 variables were defined in the "TT" global array:
sock --> sock3 count --> mycount log,cache --> type --> 2 port --> 3999 P,log --> setting --> host --> LOCALHOST server --> TT connection --> Down count,cache --> 2 reopen --> 1000 name --> LOCALHOST:3999 logfile --> NULL log --> msg_logger P,count --> up --> 0 hosts.allow --> * N --> 2 timeout --> 5000 hosts.deny --> *This server had two published variables: log and count. The variable "log" is built into the msg library, so you get it for free.
msg_register $server haltThis would register a command that could be invoked via the msg command "halt". The callback function for this command would be named TT.halt or $server.halt and would receive 4 arguments:
proc XYZ.halt { s sock msgid cmd } { }Here the 4 arguments are: