Welcome to SIMPL Programming for Python
|Course content||Enter chat room||Send email
to mailing list
In this lesson we are going to examine the detailed workings of a python gui-based sending program and a C coded 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.
The sender program in this lesson has a gui instead of a textual interface. The sending of the various messages are initiated by clicking on the various message buttons.
The messages are exactly the same as in Lessons #2 and #3.
The receiver program prints to screen the various components of the messages received.
The receiver program is exactly the same one as in Lesson #3.
With this algorithm, we hope to demonstrate the following:
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_gui3.py file. We
will examine it line by line.
1 """ 2 sender_gui.py: This is a python simpl gui-based sender. 3 Refer to lesson #4. 4 Usage: python sender_gui.py 5 """ 6 7 8 # import necessary modules 9 import sys 10 import csimpl 11 from tkinter import * 12 13 nee = None 14 15 # define the callback for button 1 16 def hndlButton1(event): 17 token = 10 18 a = 99 19 b = 999 20 c = 9999 21 nee.packMsg(nee.BIN, "iiii", token,a,b,c) 22 makeSend() 23 24 # define the callback for button 2 25 def hndlButton2(event): 26 token = 20 27 d = 3.1415 28 nee.packMsg(nee.BIN, "if", token,d) 29 makeSend() 30 31 # define the callback for button 3 32 def hndlButton3(event): 33 token = 30 34 s = "We are the knights who say Neee." 35 l = len(s) 36 nee.packMsg(nee.BIN, "iis", token,l,s) 37 makeSend() 8 39 # define the call for the simpl send 40 def makeSend(): 41 retVal = nee.send(receiverId) 42 if retVal == -1: 43 print ("%s: send error-%s" %(sName, nee.whatsMyError())) 44 sys.exit(-1) 45 46 # define the exit call 47 def die(event): 48 sys.exit(0) 49 50 # initialize some required variables 51 sName = "SENDER" 52 rName = "RECEIVER" 53 54 # create an instance of Simpl 55 nee = csimpl.Simpl(sName, 1024) 56 if nee == -1: 57 print ("%s: name attach error-%s" %(sName, nee.whatsMyError())) 58 sys.exit(-1) 59 60 # name locate the receiver 61 receiverId = nee.nameLocate(rName) 62 if receiverId == -1: 63 print ("%s: name locate error-%s" %(sName, nee.whatsMyError())) 64 sys.exit(-1) 65 66 # initialize Tk for graphics 67 root = Tk() 68 69 # set up a button to initiate the sending of message token type 10 70 button = Button(root) 71 button["text"] = "send message token type 10" 72 button.bind("
imports the csimpl module for SIMPL capability.
Line 13 sets a global variable which will become a an instance of Simpl further on.
|Lines 15-22||define a callback function that builds an outgoing message composed of an integer token and three other integers. The integer packing routines are called as instance methods and the packing type is binary because the message is being sent to a C program. Finally, the makeSend call performs the actual SIMPL Send.|
|Lines 24-37||define callback functions for other messages in a similar way as the one above.|
|Lines 51-52||define the unique SIMPL names which are treated as constants.|
|Line 55||creates the Simpl instance used to refer to all things Simpl in this program.|
|Lines 61-64||perform the simpl name locate.|
|Line 67||initializes Tkinter and loads the root variable with the required information for the root window.|
|Lines 69-73||create a button widget with text and define the function callback to be carried out in the case this button is selected. When this button is clicked on by the user a message with token type 10 will be sent to the receiver program.|
|Lines 75-79||create a button for sending messages of token type 20 to the receiver program.|
|Lines 81-85||create a button for sending messages of token type 30 to the receiver program.|
|Lines 87-91||create a button that allows the user to exit gracefully from the script.|
|Line 94||creates an infinite event loop on the root window that awaits incoming events (in this case mouse clicks on the various buttons).|
Let's examine the receiving program. Note: this is exactly the same receiving program used in Lesson #3.
2. FILE: receiver.c
3. DESCRIPTION: This is a C simpl receiver.
4. Refer to lessons 3, 4, 6, 7.
5. USAGE: receiver
8. // include required headers
9. #include <stdio.h>
10. #include <stdlib.h>
11. #include <simpl.h>
13. // define possible message structures
14. typedef struct
16. int token;
17. int var1;
18. int var2;
19. int var3;
20. } MSG1;
22. typedef struct
24. int token;
25. float var1;
26. } MSG2;
28. typedef struct
30. int token;
31. int var1;
32. char var2;
33. } MSG3;
35. int main()
37. char *me = "RECEIVER";
38. char *sender;
39. char mem;
40. int n;
41. MSG1 *in1;
42. MSG2 *in2;
43. MSG3 *in3;
44. int *token;
46. // perform simpl name attach
47. if (name_attach(me, NULL) == -1)
49. printf("%s: cannot attach name-%s\n", me whatsMyError());
53. while (1)
55. // receive incoming messages
56. n = Receive(&sender, mem, 1024);
57. if (n == -1)
59. printf("%s: Receive error-%s\n", me, whatsMyError());
63. // set a pointer to the value of the message token
64. token = (int *)mem;
66. // decide course of action based on the value of the token
67. switch (*token)
69. case 10:
70. in1 = (MSG1 *)mem;
71. Printf("token=%d var1=%d var2=%d var3=%d\n",
72. & nbsp; in1->token,
73. & nbsp; in1->var1,
74. & nbsp; in1->var2,
75. & nbsp; in1->var3);
78. case 20:
79. in2 = (MSG2 *)mem;
80. printf("token=%d var1=%d\n",
81. & nbsp; in2->token,
82. & nbsp; in2->var1);
85. case 30:
86. in3 = (MSG3 *)mem;
87. printf("token=%d var1=%d var2=%.*s\n",
89. & nbsp; in3->var1,
90. & nbsp; in3->var1,
91. & nbsp; in3->var2);
95. printf("%s: unknown message token=%d\n", me. token);
98. // reply to sender
99. Reply(sender, NULL, 0);
|Lines 9-11||include the required C header files. Note the inclusion of the simpl.h header file.|
|define the binary message that corresponds to token value 10.|
|define the binary message that corresponds to token value 20.|
|define the binary message that corresponds to token value 30.|
|is the start of the program.|
|declare necessary local variables.|
|handle the simpl name attach.|
|starts an infinite loop which awaits incoming messages.|
|receive the incoming messages.|
|sets a pointer to the incoming message token.|
|deal with each message type based on the token by printing the various message components to the screen.|
|Line 99||replies a null message to the blocked sender. This reply message could be anything at all but in the interests of simplicity, the reply message has been made null.|
The Makefile for the C receiver program.
The receiver program must be compiled and linked before it can be of any use. Go to ../src and at the command prompt type:
make cleanThen type:
make installThis makes a new executable of receiver.c called receiver and puts it in ../bin .
Note:In order to run this Makefile, the shell variable SIMPL_HOME must be set so that the make can find the simpl header and library.
Let's run the two programs.
In order to run the sender_gui3.py script and the C receiver program, do the following:
The command indicates:
You should see the receiver program print the contents of each message as you choose the various message buttons displayed by the sender gui.
Let's rerun with the C receiver in the Linode cloud.
The SIMPL surrogates come in matching sets which must be run on each end of the TCP/IP link. To enable this on your end you need to run the following SIMPL daemons in the background first:
The C receiver running on the Linode is identical to the code listed here. However in order to make the output visible via a browser the C receiver has been piped to a filter program which in turn wraps the output in HTML for perusal at:
In addition you will need to change line 52 in sender_gui.py to point at the Linode as follows:
50. # initialize some required variables
51. sName = "SENDER"
52. rName = "icanprogram.ca:RECEIVER"
and then rerun sender_gui3.py exactly as before.
Notice what happened here:The cloud based instance C receiver which has identical code to the instance we accessed locally has now been accessed remotely. The only change in the sender was the addition of the cloud URL (icanprogram.ca) in the SIMPL name for the receiver.
Let's summarize what you should have observed in this lesson: