What would it take to make a fairly general purpose server that ties into the IT infrastructure and performs more than information retrieval and still be embeddable? The author outlines the requirements, the functions supported, and discusses issues such as performance and security.
The external world knows the service from a formal definition, the WSDL document. This can be a fairly lengthy document so luckily this is produced as part of the design process (in fact it makes a really good starting point for the design) and not by the service itself. The WSDL for the reference implementation is included as an appendix. In the case of the reference implementation, we provide the ability to retrieve a copy of this definition from the device using any web browser.
The overall sequence of the application is straightforward:
Open a TCP server socket.
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 commercial 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 or the socket hits a inactivity timeout, the client handling thread closes its side and terminates.
The workhorse in the code is the client handling. It can be described very succinctly as a state machine:
For each request it tries to find a handler for the specific request. A typical GetShort request follows:
POST /DeviceIO HTTP/1.1 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 1.1.4322.573) Content-Type: text/xml; charset=utf-8 SOAPAction: "DeviceIO#GetShort" Content-Length: 313
Finding a handler makes use of a lookup table that contains a list of accepted requests (the first line in the request) and a pointer to the function that will handle this request. In the reference implementation this looks like:
The subsequent handling of soap requests by “SoapHandler” is done in a similar manner using the SOAPAction line. In the reference implementation the look up table looks like:
How we handle the parsing of XML documents is the most critical item in terms of meeting a small footprint requirement. The typical XML parser, whether of the DOM or SAX variety, is large. Since we have control of the XML layout, we can take advantage of this information to make a minimal, sequential parser. Using a list of tags and associated handlers, the parser does nothing more than find each tag, parse the “value” as a string, and invoke the associated function which knows how to convert, store etc. the item. In the reference implementation the sequence list for a SetShort XML document is:
Once the parsing is completed, the saved values are checked and the appropriate response composed and sent as the response to the original HTTP request. The response for a successful GetShort follows: