vim_util - Version-Independent Message Streams

The VIM utilities are used to send and receive version-independent messages over TCP/IP network connections. A VIM message consists of a 12-byte header followed by a list of zero or more, XDR-encoded name/value pairs. The contents of the header specify a message ID and the length of the message body.

A VIM stream is created on a previously established network connection. The following program implements a simple VIM server that periodically sends the time-of-day to a client:

    #include  <stdio.h>			-- Standard I/O definitions.
    #include  <unistd.h>		-- sleep(3) definition.
    #include  "tcp_util.h"		-- TCP/IP networking utilities.
    #include  "tv_util.h"		-- "timeval" manipulation functions.
    #include  "vim_util.h"		-- Version-independent message streams.

    int  main (int argc, char *argv[])
        VimStream  stream ;
        VimHeader  header ;
        NVList  list ;
        TcpEndpoint  client, server ;

        tcpListen (argv[1], 99, &server) ;	-- Create listening endpoint.

        for ( ; ; ) {				-- Answer next client.
            tcpAnswer (server, -1.0, &client) ;
            vimCreate (client, &stream) ;
            while (vimIsUp (client)) {		-- Send times to client.
                nvlCreate (NULL, &list) ;
                nvlAdd (list, nvpNew ("TIME", NvpTime, tvTOD ())) ;
                header.ID = 0 ;  header.parameter = NULL ;
                vimWriteList (stream, -1.0, &header, list) ;
                nvlDestroy (list) ;
                sleep (1) ;
            vimDestroy (stream) ;		-- Lost client.


The server's name is specified as the first argument on the command line (i.e., argv[1]). If a client connection is broken, the server loops back to wait for another client.

The client program below reads and displays the time-of-day messages from the VIM server:

    #include  <stdio.h>			-- Standard I/O definitions.
    #include  "tcp_util.h"		-- TCP/IP networking utilities.
    #include  "vim_util.h"		-- Version-independent message streams.

    int  main (int argc, char *argv[])
        VimStream  stream ;
        VimHeader  header ;
        NVList  list ;
        TcpEndpoint  connection ;

        tcpCall (argv[1], 0, &connection) ;	-- Call server.
        vimCreate (connection, &stream) ;
        for ( ; ; ) {				-- Read times from server.
            if (vimReadList (stream, -1.0, &header, &list))  break ;
            printf ("Server's time = %s\n", nvpString (nvlFind ("TIME"))) ;
            nvlDestroy (list) ;
        vimDestroy (stream) ;			-- Lost server.


The VIM message header contains an integer ID field and a void * parameter field that can be used by clients and servers for message identification and tagging; the VIM_UTIL package does not use these fields. Both vimRead() and vimWrite() take a timeout argument that allows the application to limit the amount of time these routines wait to perform their respective functions.

In event-driven applications (e.g., those based on the X Toolkit or the IOX dispatcher), the socket connection underlying the VIM stream, returned by vimFd(), can be monitored for input by your event dispatcher. Because input is buffered, the input callback must repeatedly call vimRead() or vimReadSet() while vimIsReadable() is true.

When a VIM stream is no longer needed, a single call will close the network connection and discard the stream:

    vimDestroy (stream) ;


The name/value pair, name/value list, and version-independent message stream packages were inspired by Mike Maloney's C++ implementations of named variables and named variable sets, and by Robert Martin's attributed data trees (see "Version-Independent Messages" in Appendix B of his Designing Object-Oriented C++ Applications Using the Booch Method).

Public Procedures

vimCreate() - creates a version-independent message stream.
vimDecode() - decodes a list of name/value pairs from a VIM message.
vimDestroy() - deletes a VIM network stream.
vimFd() - returns a VIM stream's socket number.
vimIsReadable() - checks if input is waiting to be read from a stream.
vimIsUp() - checks if a VIM stream is up.
vimIsWriteable() - checks if data can be written to a stream.
vimName() - returns the name of a VIM stream.
vimRead() - reads the next message from a VIM stream.
vimReadList() - reads an NVList message from a VIM stream.
vimWrite() - writes a message to a VIM stream.
vimWriteList() - writes an NVList message to a VIM stream.

Source Files


(See libnet for the complete source, including support routines and build files.)

Alex Measday  /  E-mail