Welcome to SIMPL Programming for Python
|Course content||Enter chat room||Send email
to mailing list
This lesson is about using SIMPL within a CGI program.
We are going do things a little differently than we have in the previous lessons. We will still be sending various possible messages to a C receiver, just as in lessons #3, #4, and #6 however, the user front end will be provided for by a web browser running a small piece of HTML code. This HTML file contains a form which is processed to retrieve the type of message to be sent. This form processing is performed by a CGI script written in Python. When the value of the appropriate form key is determined, the corresponding message is then sent to the C receiver program for processing.
In short, we will be using the same C receiver program that we used in lessons #3, #4, and #6. Accordingly, the messages will also be the same. The HTML code will provide the user input capability and the CGI script will process that input and send the corresponding message to the C receiver. It is interesting to note that where the SIMPL messages originate is of no concern to the receiver program. So far it has received messages from a local Python program (lesson #4), via the tclSurrogate (lesson #6) and now via a CGI script (lesson #7).
Again, we recommend that you read the document readme.python which is located in the docs directory below the SIMPL root directory. Pay particular attention to the final section called "SIMPL in CGI Programs".
Note:Like lesson #6, we are going to run all of the programs on one host for convenience. This would not normally be the case. A more usual scenario would be that the browser would be running in some other location than the server. Moreover, the server would likely be sending its message via the CGI script to some other remote host running the receiver program.
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 .../www directory for you to run directly.
Let's quickly examine the HTML code.
The following code can be found in the ../www/lesson7_cgi.html file.
3.<title>Python SIMPL CGI</title>
6.<H1><center>Python SIMPL CGI</center></H1>
7.<form name="tokens" method="post" action="http://localhost/cgi-bin/lesson7_cgi.py">
9. <select name="tokens" size="3">
10. <option selected>send message token type 10</option>
11. <option>send message token type 20</option>
12. <option>send message token type 30</option>
16. <input type="submit" value="send message"/>
|Lines 1-6||are the usual HTML start code.|
|Line 7||defines the form required and the CGI program that will process it. Notice the URL for the action to be taken upon submission of the form. It is http://localhost/cgi-bin/lesson7_cgi.py. The http is such that the server port will located. The localhost is such that the host that the browser is running on is selected. The cgi-bin is the directory where the server will find the CGI script to be run. Finally, the CGI script to be called is named lesson7_cgi.py.|
|Lines 8-18||produce the required user front end.|
Now, let's examine the Python CGI script.
The following code can be found in the ../www/lesson7_cgi.py file.
|1. #! /usr/bin/python
3. # required modules
4. import cgi
6. import wcsimpl
8. def sendToReceiver(value):
9. sName = "SENDER"
10. rName = "RECEIVER"
12. # attach a simpl name
13. retVal = wcsimpl.nameAttach(sName, 1024)
14. if retVal == -1:
15. toBrowser("name attach error " + wcsimpl.whatsMyError())
18. # name locate the receiver
19. receiverId = wcsimpl.nameLocate(rName)
20. if receiverId == -1:
21. toBrowser("name locate error " + wcsimpl.whatsMyError())
24. if value == "send message token type 10":
25. wcsimpl.packInt(10, wcsimpl.BIN)
26. wcsimpl.packInt(99, wcsimpl.BIN)
27. wcsimpl.packInt(999, wcsimpl.BIN)
28. wcsimpl.packInt(9999, wcsimpl.BIN)
29. elif value == "send message token type 20":
30. wcsimpl.packInt(20, wcsimpl.BIN)
31. wcsimpl.packFloat(3.1415, wcsimpl.BIN)
32. elif value == "send message token type 30":
33. wcsimpl.packInt(30, wcsimpl.BIN)
34. s = "We are the knights who say Neee."
35. l = len(s)
36. wcsimpl.packInt(l, wcsimpl.BIN)
37. wcsimpl.packString(s, wcsimpl.BIN)
39. toBrowser("unknown choice")
42. # send the message to the receiver
43. retVal = wcsimpl.send(receiverId)
44. if retVal == -1:
45. toBrowser("send error " + wcsimpl.whatsMyError())
49. def toBrowser(str):
50. print "Content-type: text/html\n"
51. print "<HTML>\n"
52. print "<HEAD>\n"
53. print "<TITLE>%s</TITLE>\n" %("Python SIMPL CGI")
54. print "</HEAD>\n"
55. print "<BODY>\n"
56. print "<H1><center>%s</center></H1>\n" %str
57. print "</BODY>\n"
58. print "</HTML>\n"
61. # operational part of the program
63. # get the form parameters
64. form = cgi.FieldStorage()
66. # check for a form
67. if not form:
68. # no form available
69. toBrowser("no form available")
71. # process form parameter
72. key = "tokens"
73. if form.has_key(key):
74. value = form.getvalue(key)
75. # SIMPL send the chosen message to the receiver
78. toBrowser("no message type")
80. # detach SIMPL name
|Lines 4-6||import the required modules. Note line 5; it is commented out but when it is uncommented it will dump information to the browser regarding the server being used. It can be very useful for debugging.|
|Lines 8-45||define a function used to build the message and perform the SIMPL send to the C receiver.|
|Lines 9-10||define the SIMPL names of the sender and the receiver.|
|Lines 13-16||attach unique SIMPL name.|
|Lines 19-22||SIMPL name locate the receiver program.|
|Lines 24-40||build the message to be sent to the receiver.|
|Lines 43-45||perform the SIMPL send to the receiver.|
|Lines 49-58||define a function to send messages back to the browser.|
|Lines 64-81||define an HTML form, retrieve the form key that determines the type of message to be sent to the receiver, and finally perform a SIMPL name detach.|
Let's examine the receiving program. Note: this is exactly the same receiving program used in Lessons #3, #4, and #6.
The following code can be found in the ../src/receiver.c file.
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 files and library.
The Web Server.
In order to continue with this lesson and be able to run the programs, the web server needs to be checked for certain configuration issues. Again, we recommend that you read the document readme.python which is located in the docs directory below the SIMPL root directory. Pay particular attention to the subsection called "Web Server".
As previously stated we are going to use the Apache web server. In order for Apache to perform as required, it may be necessary for Apache's configuration file to be modified. Let us say that that file is /etc/httpd/conf/httpd.conf. Let us also say that the html, cgi, etc. files accessed and used by Apache are located in subdirectories below /var/www. The following are some of the things that have to be set for the Apache server to be able to function correctly:
Let's run the programs.
In order to run this lesson's programs do the following:
Let's rerun with the C receiver and the webserver in the cloud
Recall that in previous lessons we had arranged to run the C receiver on the Linode at icanprogram.ca. The output from the C receiver was piped into a filter process which in turn wrapped that output in HTML for display at:
We also have arranged for the Python-CGI to be available to the webserver on the Linode. To run in this mode the URL is:
Notice what happened here:The very same cloud based instance of C receiver that we accessed via the TCP/IP SIMPL surrogate and tclSurrogate in previous lessons has now been accessed remotely from a browser using Python as the CGI script. NO CHANGES whatsoever were required in the C receiver code to achieve this. It is identical code to the C receiver you accessed locally in these same lessons.
Let's summarize what you should have observed in this lesson:
The SIMPL toolkit allows you to build modules that are
This is the SIMPL toolkit's value proposition.
End of Lesson 7.