Accessing Devices Using a Web Service - Web Service Implementation
(Page 4 of 5 )
We have now covered the background and design of our Web service application. Lets take a look at the key parts of implementation. First a couple of key points about the implementation:
- The example is a typical “server” type socket application with a minimal console human interface.
- Key parameters used by the Web service application are provided in a small configuration file, web.cfg.
- The examples, both Windows and Linux versions, were implemented in C++ as standalone programs. They can be easily ported to straight C where C++ is not supported and/or included as part of an existing piece of software.
- The primary external facilities required are a socket interface to a TCP/IP communication stack and support for threading.
- The source code for both Windows and Linux versions can be downloaded from http://the-solution-llc.com/webservice.zip.
The overall sequence of the application is straightforward:
- Open a server type socket on TCP port 80.
- Wait for a client connection.
- For each client connection start a new thread to handle the client’s requests (NOTE: The thread per client model is fine for cases where a relatively small number of simultaneous connections is maintained. In the big time Web server arena where the number of connections is in the thousands this does not work well. Then you have to do things like thread pooling).
- The client handling thread waits for a complete HTTP request and based on the request provides the appropriate response.
- When the client closes the socket, the client handling thread closes its side and terminates.
The workhorse is the code in the client handling class, client.cpp. It can be described very succinctly as a state machine:

For each request it copies the HTTP version signature of the request, we need that in the response, and then tries to find a handler for the specific request. Finding a handler makes use of a lookup table that contains a list of accepted requests and a pointer to the function that will handle this request.
struct request_handler
{
char *name;
void (*function)(class client_handler *,char *);
};
<P align=left>
<P align=left>struct request_handler client_handler::request_handlers[] =
{
{"get /version ",SendVersion},
{"get /listener.htm ",SendListener},
{"get /time ",SendTime},
{"",NULL}
};
This simple implementation of matching request and response handlers provides decent scalability and is easily modified to meet any specific need.
An XML response is nothing more then the dynamic composition and transfer of the appropriate XML response “document”. A short code snippet from the Linux version time request handler will illustrate:
time_t t
;
struct tm *today;
char hr_line[20],min_line[20],sec_line[20];
<P align=left>
t = time(NULL);
today = localtime(&t);
sprintf(hr_line,"<Hour>%02d</Hour>",today->tm_hour);
sprintf(min_line,"<Minute>%02d</Minute>",today->tm_min);
sprintf(sec_line,"<Second>%02d</Second>",today->tm_sec);
From the client point of view it has made a request and is provided data in the form of a document as the response. Because of the nature of this document, individual items can be easily found and parsed using off-the-shelf software and displayed. The simple listener HTML page, listener.htm, in the example does exactly this using Visual Basic script and the Microsoft XML parser (a COM object). The example could just as easily been implemented in other forms such as a stand alone “web application” using Visual Basic, Java or C++ and any number of XML parsers.
The example client uses the Document Object Model (DOM) parser. The DOM presents an easily processed standardized interpretation of an XML document to applications and scripts that is well suited to relatively small documents. The basic operation of the example is:
Load the appropriate XML document
Find each data element required by its tag name.
Remove the text value of the element.
Manipulate the text as necessary and display.
The sub-routine that takes care of updating the HTML pages time field illustrates just how simple this is:
[/code]
Sub UpdateTime
Dim elemlist
Dim xmldoc
Dim hr_stg
Dim min_stg
Dim sec_stg
dim success
Set xmldoc = CreateObject("Msxml.DOMDocument")
xmldoc.async = False
xmldoc.validateOnParse = False
Err.Clear
On Error resume next
xmldoc.Load("http://" + web_path + "time")
If xmldoc.documentElement.baseName = "Time" Then
Set elemlist = xmldoc.getElementsByTagName("Hour")
hr_stg = elemlist.Item(0).Text
Set elemlist = xmldoc.getElementsByTagName("Minute")
min_stg = elemlist.Item(0).Text
Set elemlist = xmldoc.getElementsByTagName("Second")
sec_stg = elemlist.Item(0).Text
WebTime.Value = hr_stg + ":" + min_stg + ":" + sec_stg
Else
WebTime.Value = "Error"
End If
On Error GoTo 0
End Sub
[/code]
Next: Conclusion >>
More Web Services Articles
More By Terry Ess