The old days when embedded devices and factory floor machines had only minimal interaction with humans, the on/off button and little else, are gone. Today the ability to access the device from anywhere is expected. This is a significant challenge when we are sweating over every dollar required in hardware. With a little bit of knowledge and a relatively small piece of software, we can provide a Web service for this type of interaction.
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 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.
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