Remote printf facility
rmtprint.h         rmtphost.c         rmtpclient.c
I wrote this utility when I was investigating how tcp⁄ip and socket calls worked.
At the time I was working on a Unix pre-Windows system which displayed output on the screen using ascii terminal control characters. The system was very primitive and there were no good debuggers so I wanted to add printf statements ("poor man's debugging") to the code. I did not want these statements to interfere with the formatted screen so I devised a scheme called Remote Printf.
Remote printf works like this:
The program being debugged is the client. When a debugging printf statement is needed the routine remotePrintf (or remotePuts, etc.) is called. The prototype for remotePrintf is identical to the regular printf statement: a format string followed by a variable number of arguments.
In another window, or perhaps on another machine, the remoteprintf server is running. It is listening on a known socket. When the client calls remoteprintf, a message is written to that socket containing the remoteprintf output.
The server receives that message and displays it in its own window, thereby not interfering with the client window.
As I mentioned above, this program was really written so I could investigate how tcp⁄ip and sockets worked. As such, the following documents in excruciating detail how the program works, both for the reader, and for myself as a reminder.
Note: In the code there are several references to the symbol WIN32. The code does not work on Windows (it does work on a Macintosh). I am in the process of fixing it up to do so.
Message Structure (in rmtprint.h)
Messages are passed to the server (host) process in a message block.
If the message is remoteGets, the user's reply is passed back in the same block.
Here is the format of the block:
  | message length (msgLen) - includes all the following fields    |
  | message identifier (masgID) - unique for each request-response |
  | message client (msgClient) - process ID of requesting process  |
  | message type (msgType) - indicates type of message contents    |
  | message body (msgBody) - contents of message, variable length  |
  | - terminated with string terminator                            |
  |                               ...                              |
  |                               ...                              |
  |                               ...                              |
Host (rmtphost.c)
    opensocket()         creates and opens socket, calls listen to start listeninng
    getBinarySemaphore         gets a resource used for synchronization in handleRequest
         acceptSocket() waits for message to be received
         getMessage() reads entire message possibly using multiple calls to readSocket()
         if request type is RMTP_STOP
             break out of the loop
         run handleRequest() in a forked subprocess to handle the message
         so that more than one request can be in process at the same time
         continue with the loop to handle the next request
    End of Loop
    deleteBinarySemaphore deletes the synchronization resource
    closeSocket releases the socket
handleRequest (forked subprocess run on host to handle message)
    lock the synhronization resource so that simultaneous messages do not interfere with each other
    Display text sent with request with no line termination
    Request-specific processing
         print line terminator
         flush the print buffer to print without line terminator
         get input from the user using fgets
         should not happen, print offending message
    unlock the synchronization resource
    if this request was RMTP_GETS
         formulate the response and send it back to the client using writeSocket()
    exit the subprocess
Client (rmtpclient.c):
    Each remotePrint routine does similar processing:
    format the message according to the call, puts, gets, fputs, printf
    call sendMessage to
         open a socket connection to the host
         send the message to the host using writeSocket()
    if this is a remoteGets call
         call getReply to get the reply text
    Unless this is a remoteGets call the socket is closed after the message is sent
    If this is a remoteGets call the socket remains open to receive the response
    After the response is received, the socket is closed
    There are also 3 ways (based on #defines) to build the client as a test stub with a main routine.
         RMTPCLIENT: build with a main() routine that
                      prompts the user to send test strings
         RMTPCLIENT: build with a main() routine that
                      sends a specified number of test messages
         RMTPSTOP:   build with a main() routine that
                      sends a single message to shut down the server
Previous  |  Next ]     [ Up  |  First  |  Last ]     (Article 17 of 485)
Comments, flames, broken links?
Please send email to