I. background
The background of this article is the interface between the 12th Five-Year Plan and the systematics Integrated Monitoring of Westinghouse. The history recorder service is deployed as an interface for external data publishing. The history recorder service allows the systematics service to configure object data and list data to be stored and forwarded to external system processing software. The external system processing software needs to be configured in history recorder so that the integrated monitoring software can monitor its connection status. You can use a file or configuration tool to configure the history recorder service. The configuration information mainly includes:
• Indicates the path of the application to which data is sent;
• The data to be sent to the application;
• The table to be sent to the application.
The history recorder Service uses the HTTP protocol to send data to the external system. ISCS will actively connect to the external system's Web Service Based on the configuration. After the first connection, all data will be sent, the changed data will be sent and all data will be updated on a regular basis. The Web Service of the external system must respond to at least the first three HTTP messages (200 OK response ).
The format of the sending device status (data point) is as follows:
--------------- HTTP header ------------------
Post, HTTP, 1.1
HOST: 192.10.36.36: 808
Content-location: oil: // SCADA. TMS/hpx_prc_do_0000
Content-Type: Application/Calendar + XML
Content-Length: 111
--------------- Data zone ------------------
<Vjournal>
<Tags> bad </tags>
<Dtstart> 2009-02-25t10: 01: 19.933723z </dtstart>
<Description> 1 </description>
</Vjournal>
--------------- End ------------------
When data is sent, the content is encapsulated in an XML package. Based on these situations, Westinghouse's external interface is similar to the SOAP protocol.
Ii. lacewing
This article describes how to integrate Web server into your Win32 C ++ application. C ++ Web applications written using the lacewing network library provide faster speed and good scalability, and occupy extremely low system resources. Liblacewing is a cross-platform advanced network library for C and C ++. It aims to provide a set of intuitive Socket Communication classes, focusing on stability and platform optimization (iocp, epoll, and kqueue are supported ).
Lacewing: as a powerful HTTP server, webserver has the following features:
• Http get/post with Automatic Parameter Parsing
• Non-blocking File Sending
• Cookies and sessions
• Multipart File Upload
• Getting/setting the Last modified Date, to easily implement caching
• Full HTTPS support
Lacewing source code: A http://lacewing-project.org/
Iii. Test Environment
1. Operating System
Windows 7
2. System
Processor: Intel (r) core (TM) i5-2401M CPU @ 2.30gh 2.30gh
Installed memory: 3.00 GB (2.88 GB available)
System type: 32-bit Operating System
3. tool environment
A. VC ++ 6.0
B. vs2008
4. Create a web server project
Download the lacewing source code. After compiling with vs2008, lacewind. dll and lacewing. Lib will be generated in the bin directory.
Use vs2008 to create a testwebserver Win32 console project. Copy lacewind. dll and lacewing. lib to the project file directory, and configure the lacewing. Lib file in the project properties.
// Testwebserver. CPP: defines the entry point for the console application. // # include "lacewing. H "# include <assert. h> # include <string. h> # import <msxml4.dll> using namespace msxml2; void paserxml (BSTR bstxml) {msxml2: ixmldomdocumentptr pdoc; hresult hr; HR = pdoc. createinstance (_ uuidof (msxml2: domdocument40); If (failed (HR) {printf ("The domdocument object cannot be created. Check whether the ms xml Parser Runtime library is installed! "); Return;} Try {// load the file // pdoc-> load (" test. XML "); pdoc-> loadxml (bstxml); long lchilds, I; // root node msxml2: ixmldomelementptr prootelement = pdoc-> getdocumentelement (); printf ("root = % s \ n", (char *) prootelement-> getnodename (); // msxml2 :: ixmldomnodelistptr pnodelist = prootelement-> getchildnodes (); lchilds = pnodelist-> getlength (); char sznodename [48], szvalue [64]; for (I = 0; I <lchilds; I ++) {Msxml2: ixmldomnodeptr pnode = pnodelist-> getitem (I); // filter comment nodes if (pnode-> getnodetype ()! = Msxml2: node_comment) {BSTR bstrnodename = pnode-> getnodename (); char * Signature = _ com_util: convertbstrtostring (bstrnodename); strncpy (sznodename, expires, sizeof (sznodename); Delete [] bytes; BSTR bstrvalue = pnode-> gettext (); char * lpszvalue = _ com_util: convertbstrtostring (bstrvalue); strncpy (szvalue, lpszvalue, sizeof (szvalue); Delete [] lpszvalue; printf ("% s: % s \ n", sznodename, szvalu E) ;}} catch (_ com_error & E) {printf ("Description = '% s' \ n", (char *) E. description (); If (pdoc) {pdoc. release () ;}} void onget (lacewing: webserver &, lacewing: webserver: Request & request) {/* the MIME type defaults to "text/html" */request. setmimetype ("text/html"); Request. writefile ("post.html");} void onpost (lacewing: webserver & Webserver, lacewing: webserver: Request & request) {// here the szbody will display HTTP XML formatted data sent by post // <vjournal> // <tags> bad </tags> // <dtstart> 2009-02-25t10: 01: 19.933723z </dtstart> // <description> 1 </description> // </vjournal> char * szbody = (char *) request. body (); BSTR bstrbody = _ com_util: convertstringtobstr (szbody); paserxml (bstrbody);: sysfreestring (bstrbody); Request <"Hello systematics! "; Struct lacewing: webserver: Request: Header * Header = NULL; For (header = request. firstheader (); header = header-> next () {const char * szname = header-> name (); const char * szvalue = header-> value ();} lacewing: webserver: Request: parameter * P = NULL; For (P = request. post (); P = p-> next () {const char * szname = p-> name (); const char * szvalue = p-> value () ;}} int main (INT argc, char * argv []) {coinitialize (null); lacewing: eventpump; lacewing:: webserver (eventpump); webserver. onget (onget); webserver. onpost (onpost); webserver. host( 8080); eventpump. starteventloop (); couninitialize (); Return 0 ;}
5. Create an http post Project
Use vs6 to create a testhttppost Win32 console project.
// Testhttppost. CPP: defines the entry point for the console application. // # include "stdafx. H "# include <string> # include <iostream> # import <msxml4.dll> using namespace msxml2; STD: wstring generatedata () {STD: wstring wvarquery; ixmldomdocumentptr pdoc; ixmldomelementptr xmlroot; // create the domdocument object hresult hR = pdoc. createinstance (_ uuidof (domdocument40); If (! Succeeded (HR) {printf ("The domdocument object cannot be created. Check whether the ms xml Parser Runtime library is installed! "); Return wvarquery;} // The root node name is vjournal // create an element and add it to the document xmlroot = pdoc-> createelement (" vjournal "); pdoc-> appendchild (xmlroot); ixmldomelementptr pnode; // Add the "tags" element pnode = pdoc-> createelement ("tags"); pnode-> puttext (const char *) "bad"); xmlroot-> appendchild (pnode); // Add the "dtstart" element pnode = pdoc-> createelement ("dtstart "); pnode-> puttext (const char *) "2009-02-25t10: 01: 19.933723z"); xmlroot-> appendchild (pnode); // Add the "Description" element pnode = pdoc-> createelement ("Description"); pnode-> puttext (const char *) "1 "); xmlroot-> appendchild (pnode); // save it to the file and overwrite it if it exists. Otherwise, it is created if it does not exist. // pdoc-> Save ("test. XML "); wvarquery = pdoc-> getxml (); Return wvarquery;} void paserxml (BSTR bstxml) {ixmldomdocumentptr pdoc; hresult hr; HR = pdoc. createinstance (_ uuidof (domdocument40); If (failed (HR) {printf ("The domdocument object cannot be created. Check whether Ms xml p is installed. Arser Runtime library! "); Return;} // load the file // pdoc-> load (" test. XML "); // load the memory pdoc-> loadxml (bstxml); long lchilds, I; // The root node ixmldomelementptr prootelement = pdoc-> getdocumentelement (); printf ("root = % s \ n", (char *) prootelement-> getnodename ()); // ixmldomnodelistptr pnodelist = prootelement-> getchildnodes (); lchilds = pnodelist-> getlength (); char sznodename [48], szvalue [64]; for (I = 0; I <lchilds; I ++) {ixm Ldomnodeptr pnode = pnodelist-> getitem (I); // filter annotation node if (pnode-> getnodetype ()! = Node_comment) {BSTR comment = pnode-> getnodename (); char * Comment = _ com_util: convertbstrtostring (bstrnodename); strncpy (sznodename, struct, sizeof (sznodename )); delete [] values; BSTR bstrvalue = pnode-> gettext (); char * lpszvalue = _ com_util: convertbstrtostring (bstrvalue); strncpy (szvalue, lpszvalue, sizeof (szvalue )); delete [] lpszvalue; printf ("% s: % s \ n", sznodename, szvalue );}}} Void senddata (STD: wstring URL) {long lstate, lstatus; hresult hr; ixmlhttprequestptr pixmlhttprequest; ixmldomdocumentptr pxmldoc; try {hR = pixmlhttprequest. createinstance (_ uuidof (XMLHTTP); succeeded (HR )? 0: Throw hr; HR = pixmlhttprequest-> open ("Post", URL. c_str (), false); succeeded (HR )? 0: Throw hr; // if you want to post data to the server, set this field to application/X-WWW-form-urlencoded pixmlhttprequest-> setRequestHeader ("Content-Type ", "Application/X-WWW-form-urlencoded"); STD: wstring wvarquery = generatedata (); _ variant_t vartqueryfields (wvarquery. c_str (); paserxml (vartqueryfields. bstrval); HR = pixmlhttprequest-> send (vartqueryfields); succeeded (HR )? 0: Throw hr; // process the returned XML data and parse the returned XML data, mainly Dom methods. pxmldoc = pixmlhttprequest-> responsexml; // retrieve the statepixmlhttprequest-> get_readystate (& lstate); If (lstate = 4) {// The request has completed. // get the Request status. pixmlhttprequest-> get_status (& lstatus); If (lstatus = 200) {// get the response body if we were successful. BSTR bstrbody; pixmlhttprequest-> get_responsetext (& bstrbody); char * l Pszbody = _ com_util: convertbstrtostring (bstrbody); // The data "Hello systematics!" In the webserver body area is displayed !" Delete [] lpszbody ;}}catch (_ com_error & E) {printf ("Description = '% s' \ n", (char *) E. description (); If (pixmlhttprequest) {pixmlhttprequest. release ();} If (pxmldoc) {pxmldoc. release () ;}} int main (INT argc, char * argv []) {coinitialize (null); senddata (L "http: // localhost: 8080 "); couninitialize (); Return 0 ;}
Vi. Test
1) HTTP client sending:
Post, HTTP, 1.1
Accept :*/*
Accept-language: ZH-CN
Content-Type: Application/X-WWW-form-urlencoded
Accept-encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; slcc2 ;. net CLR 2.0.50727 ;. net CLR 3.5.30729 ;. net CLR 3.0.30729; Media Center PC 6.0 ;. net4.0c ;. net4.0e)
HOST: localhost: 8080
Content-Length: 113
Connection: keep-alive
Cache-control: No-Cache
<Vjournal> <tags> bad </tags> <dtstart> 2009-02-25t10: 01: 19.933723z </dtstart> <description> 1 </description> </vjournal>
Note:At the end of the text is "\ r \ n.
2) receive HTTP Server:
Post, HTTP, 1.1
Accept :*/*
Accept-language: ZH-CN
Content-Type: Application/X-WWW-form-urlencoded
Accept-encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; slcc2 ;. net CLR 2.0.50727 ;. net CLR 3.5.30729 ;. net CLR 3.0.30729; Media Center PC 6.0 ;. net4.0c ;. net4.0e)
HOST: localhost: 8080
Content-Length: 113
Connection: keep-alive
Cache-control: No-Cache
<Vjournal> <tags> bad </tags> <dtstart> 2009-02-25t10: 01: 19.933723z </dtstart> <description> 1 </description> </vjournal>
Note:At the end of the text is "\ r \ n.
3). HTTP Server Response:
"HTTP/1.1 200 OK \ r \ ncontent-length: 0 \ r \ n"
That is:
HTTP/1.1 200 OK
Content-Length: 0
Note:At the end of the text is "\ r \ n. If the length is 0, the body is a null string.
End