Welcome to SIMPL Programming for Python
Lesson #2

Course content Enter chat room Send email 
to mailing list
Check calendar

Lesson Overview

In this lesson we are going to examine the detailed workings of a python text-based sending  program and a python text-based receiving program.

The sender program is able to send three different types of messages and the receiver program to receive these messages and react appropriately.

With this algorithm we hope to demonstrate the following:
 

  1. tokenized message passing,
  2. how the sender can create the messages,
  3. how the receiver can extract the relevant information from these messages, and
  4. how to use the SIMPL module functionality in various ways.

 

Note:

Do NOT cut and paste the following code pieces. The scripts are available in the .../src directory for you to run directly.

Let's examine the sending script.

The following code can be found in the ../src/sender_txt3.py file. We will examine the important points by line number.
 
      1 """
      2 sender_txt3.py: This is a python simpl text-based sender.
      3 Refer to lessons #2 and #3.
      4 Usage: python3 sender_txt3.py tokenType
      5 """
      6 
      7 
      8 # import required modules
      9 import sys
     10 import csimpl
     11 
     12 # initialize necessary variables
     13 sName = "SENDER"
     14 rName = "RECEIVER"
     15 
     16 # create an instance of Simpl
     17 nee = csimpl.Simpl(sName, 1024)
     18 if (nee == -1):
     19         print ("name attach error-", whatsMyError())
     20         sys.exit(-1)
     21 
     22 # name locate the receiver program
     23 receiverId = nee.nameLocate(rName)
     24 if receiverId == -1:
     25         print ("name locate error-",  nee.whatsMyError())
     26         sys.exit(-1)
     27 
     28 # compose the message you wish to send based on the value of the token 
     29 if sys.argv[1] == "10":
     30         print ("token = 10") 
     31         nee.packMsg(nee.BIN, "iiii", 10,99,999,9999)
     32 
     33 elif sys.argv[1] == "20":
     34         print ("token = 20")
     35         nee.packMsg(nee.BIN, "if", 20,3.1415)
     36 elif sys.argv[1] == "30":
     37         print ("token = 30")
     38         s = "We are the knights who say Neee."
     39         l = len(s)
     40         print ("str=",s)
     41         nee.packMsg(nee.BIN, "iis", 30,l,s)
     42 else:
     43         print ("unknown message type")
     44         sys.exit(-1)
     45 
     46 # send the message
     47 retVal = nee.send(receiverId)
     48 if retVal == -1:
     49         print ("send error-",  nee.whatsMyError())
     50         sys.exit(-1)

Line 10 imports the csimpl module. This module is responsible for supplying the SIMPL functionality to the Python script.
Lines 13 and 14 set the unique SIMPL names for the sender and the receiver programs. These names could be any type of string which is convenient. In this case the names are in uppercase implying that they are constants.
Line 17 creates an instance of Simpl. Like the tkinter module for example, the csimpl module API allows the programmer to call the various aspects of csimpl via a class instance or as module functions, depending on the application's needs and/or programming tastes.
Lines 17-20 make the necessary nameAttach() call that must precede all other SIMPL calls because nameAttach() is responsible for much of the required initialization required by SIMPL. This program is a SIMPL sender so it attaches the name created for the sender above. The parameter 1024 tells SIMPL that the largest expected incoming or outgoing message will not be larger than 1 kbyte. The call to whatsMyError() returns a string describing the SIMPL error, if encountered.
Lines 23-26 make a SIMPL nameLocate() call that returns the unique SIMPL ID of the receiving program that a message will be sent to. This is required for the SIMPL send() call to follow.
Lines 28-42 compose the message that will be sent to the receiver. Notice that all of the pack() methods contain an argument called BIN. This instructs the pack() software how to organize the data elements within the message. The possibilities are BIN or CHR. BIN instructs the packing/unpacking routines to write/read message items to/from the message memory with a binary approach to the memory; like a C binary structure. BIN would be used when sending to or receiving from a C program that uses structures as their message definitions. BIN based messages are usually larger in size because they must give deference to memory boundaries. CHR tells the packing/unpacking routines to simply read/write data items byte by byte. CHR is used when BIN is unnecessary.
Lines 29-31take the value of the token passed into the script on the command line as 10. This number serves as a "token" for the message. A token is a unique identifier which allows the receiving program to understand the message data to follow within a received message. In this case, the sender packs three integers, namely 99, 999, and 9999. When the receiver unpacks the message it is understood that the first thing in the message is an integer token which will direct any further unpacking. Hence, in this case a token value of 10 indicates that three more integers are to follow in the message content.
Lines 33-35take a token value of 20 and build a message containing a floating point number. Note that in C, floats are four byte signed numbers, while in Python all floats are C doubles (eight byte signed numbers). If all of the SIMPL programs are written in one language (Python say) and reside on similar platforms (32-bit say), then less attention needs to be paid in packing/unpacking messages. On the other hand, if the languages/platforms used view data types differently, care must be taken that the appropriate types are used when composing messages in order to preserve the proposed meaning of the message content.
Lines 36-41 use a token value of 30 and create a message containing a string. Notice that the length of the string is also sent as part of the message so that the receiver knows how long the string actually is.
Lines 47-50 perform the actual SIMPL sending of the message to the receiving program. There are no unpack() calls after the send() indicating that there is no expected reply in this case. Often, there is a reply of some sort from the receiver, but for the sake of simplicity in this example, a reply message has been omitted.

 

Let's examine the receiving script.

The following code can be found in the ../src/receiver_txt3.py file. We will examine it line by line.
 
      1 """
      2 receiver_txt3.py: This is a python simpl text-based receiver.
      3 Refer to lesson #2.
      4 Usage: python3 receiver_txt3.py
      5 """
      6 
      7 
      8 # import required modules
      9 import sys
     10 import csimpl
     11 
     12 # set this program's name
     13 rName = "RECEIVER"
     14 
     15 # enable this script to utilize simpl
     16 nee = csimpl.Simpl(rName, 1024)
     17 if (nee == -1):
     18         print ("name attach error-" .whatsMyError())
     19         sys.exit(-1)
     20 
     21 # receive and process a message
     22 while 1:
     23         # receive a message
     24         messageSize, senderId = nee.receive()
     25 
     26         # check for error
     27         if messageSize == -1:
     28                 print ("receive error-" , nee.whatsMyError())
     29                 sys.exit(-1)
     30         # is it a non-null message?
     31         elif messageSize > 0:
     32                 # extract the token from the message
     33                 token = nee.unpackMsg(nee.BIN, "i")
     34 
     35                 # react on token value
     36                 if token == 10:
     37                         a,b,c = nee.unpackMsg(nee.BIN, "iii")
     38                         print ("token=%d a=%d b=%d c=%d" %(token, a, b, c))
     39                 elif token == 20:
     40                         d = nee.unpackMsg(nee.BIN, "f")
     41                         print ("token=%d d=%f" %(token, d))
     42                 elif token == 30:
     43                         length,myStr = nee.unpackMsg(nee.BIN, "i32s")
     44                         print ("token=%d len=%d str=%s" % (token, length ,myStr))
     45                         print ("str= ", myStr)
     46                 else:
     47                         print ("unknown token type=%d" % token)
     48 
     49         # reply to sending program
     50         retVal = nee.reply(senderId)
     51         if retVal == -1:
     52                 print ("reply error-" , nee.whatsMyError())
     53                 sys.exit(-1)

Line 10 imports the csimpl module. For the sake of generality, the SIMPL functionality will be called as module functions in the code to follow; that is, in comparison with the sender code above.
Line 16 make the necessary nameAttach() call that must precede all other SIMPL calls. This program is a SIMPL receiver so it attaches the name created for the receiver above. The 1024 tells SIMPL that the largest expected incoming or outgoing message will not be larger than 1 kbyte.
Line 22 starts an infinite loop wherein messages are received, processed, and replied to indefinitely.
Line 24 performs the actual blocking receive. The receive() call returns the message size in bytes and the SIMPL ID of the sending program which is needed for the reply().
Lines 27-29 handle the case of an error. Errors are flagged by a return value of -1 from receive() in the returned message size.
Line 31 ascertains that there is indeed a message because the message size is not zero. It is indeed possible to send a message with no content which would then be of zero size.
Line 33 unpacks the token from the incoming message. The token is always present at the beginning of a message. The token which was set by the sending program, provides a unique identifier to the receiving program so that how the message content is to be interpreted and dealt with is clearly understood.
Lines 35-48 handle the message based on the value of the token. In each case, the relevant message structure values are unpacked and printed out to the screen.
Lines 50 reply a NULL message to the send blocked sending program. The reply message is NULL for the sake of simplicity, but often there is a reply message to be sent back to the sender.

 

Let's run the two scripts.

In order to run the above programs, sender_txt3.py and receiver_txt3.py, do the following:

  1. make sure that PYTHONPATH has been exported to your shell.
    ie. export PYTHONPATH=$(SIMPL_HOME)/python/modules
  2. open a shell window. This can be opened from a desktop such as KDE or GNOME.
  3. in this shell window,  change directory to src.
  4. start the python receiver program. That is at the command line prompt type: python3 receiver_txt3.py
  5. open another shell window next to the first one.
  6. again change directory to src.
  7. this time, run the sender program. That is,  at the command prompt type: python3 sender_txt3.py 10


This last command indicates:

  1. the python interpreter is to run this script,
  2. the script to run is sender_txt3.py,
  3. the message to send is the one identified by token = 10.


You should see the receiver program report the contents of the message identified by token=10 printed in the first shell window.  Repeat step 7 but using  the token numbers 20 and 30. Again, the contents of these messages should be printed out on the shell window by the receiver program.
 

To end the receiver program, simply enter <cntl>-c.
 

Summary

Let's summarize what you should have observed in this lesson:

End of Lesson 2.


Copyright of iCanProgram Inc.  2012