使用lacewing解決HTTP+XML介面問題

來源:互聯網
上載者:User

一、背景

        文章背景來源於十二五課題與西屋的SystematICS綜合監控的介面問題,其中History Recorder服務部署為對外資料發布的介面。History Recorder服務允許SystematICS服務物件資料和列表資料配置成儲存並轉寄給外系統處理軟體。外系統處理軟體需要在History Recorder中配置,這樣綜合監視軟體可以監視它的串連狀態。可以使用檔案或者組態工具配置History Recorder服務,需要配置的資訊主要有:

        •   表示資料要發送到的應用程式的路徑;

        •   所要發送給應用程式的資料;

        •   所要發送給應用程式的表格。

        History Recorder服務使用HTTP協議向外系統發送資料,ISCS將根據配置主動串連到外系統的web服務,首次串連後將發送全部資料,之後將發送變化資料並定期更新全部資料。外系統的web服務需至少響應前3個http訊息(回應200 OK)。

發送裝置狀態(資料點)的格式如下:

---------------http頭------------------

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區------------------

<vjournal>

   <tags>bad</tags>

   <dtstart>2009-02-25T10:01:19.933723Z</dtstart>

   <description>1</description>

</vjournal>

---------------結束------------------

    發送資料時是以XML包封裝內容,基於這些情況描述,西屋的對外介面類似SOAP協議。

二、Lacewing

        這篇文章主要講述怎樣把Web Server整合到你的Win32 C++應用中。使用lacewing網路程式庫編寫的C++ Web應用程式具有更快的速度和良好的伸縮性,佔用系統資源極低。liblacewing 是一個跨平台的進階網路程式庫,用於C和C++。旨在提供一組直觀的Socket通訊類,側重於穩定性和平台最佳化(支援IOCP, epoll 和kqueue)。

        Lacewing::Webserver 作為一個功能強大的HTTP server, 主要有以下特徵:

        •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原始碼:http://lacewing-project.org/

三、測試環境

1、 作業系統

         WINDOWS 7

2、系統

         處理器:Intel(R) Core(TM) i5-2401M CPU @ 2.30GH 2.30GH

         安裝記憶體:3.00GB (2.88 GB可用)

         系統類別型:32位作業系統

3、工具環境

         A、vc++6.0

         B、VS2008

四、建立Web Server Project

        下載Lacewing原始碼,使用VS2008編譯之後會在bin目錄下產生lacewind.dll和lacewing.lib。

        使用VS2008建立一個testWebServer WIN32控制台工程。同時,把lacewind.dll和lacewing.lib複製到工程檔案目錄下,在工程屬性中配置包含lacewing.lib檔案。

// 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("無法建立DOMDocument對象,請檢查是否安裝了MS XML Parser 運行庫!");        return ;    }    try    { // 負載檔案// pDoc->load("test.xml");pDoc->loadXML(bstXML);long lChilds, i;// 根節點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);// 過濾注釋節點if (pNode->GetnodeType() != MSXML2::NODE_COMMENT){BSTR bstrNodeName = pNode->GetnodeName();char *lpszNodeName = _com_util::ConvertBSTRToString(bstrNodeName);strncpy(szNodeName, lpszNodeName, sizeof(szNodeName));delete []lpszNodeName;BSTR bstrValue = pNode->Gettext();char *lpszValue = _com_util::ConvertBSTRToString(bstrValue);strncpy(szValue, lpszValue, sizeof(szValue));delete []lpszValue;printf("%s:%s\n", szNodeName, szValue);}}}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){// 這裡szBody將顯示HttpPost發送的XML格式化資料//<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 = Header->Next())    {       const char *szName = Header->Name();const char *szValue = Header->Value();    }        Lacewing::Webserver::Request::Parameter *p = NULL;    for (p = Request.POST(); p; p = p->Next())    {const char *szName = p->Name();const char *szValue = p->Value();    }}int main(int argc, char * argv[]){    CoInitialize(NULL);    Lacewing::EventPump EventPump;    Lacewing::Webserver Webserver(EventPump);    Webserver.onGet(onGet);    Webserver.onPost(onPost);    Webserver.Host(8080);        EventPump.StartEventLoop();    CoUninitialize();    return 0;}

五、建立HTTP Post Project

       使用VS6建立一個testHttpPost WIN32控制台工程。

// 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;// 建立DOMDocument對象HRESULT hr = pDoc.CreateInstance(__uuidof(DOMDocument40));if (!SUCCEEDED(hr)){  printf("無法建立DOMDocument對象,請檢查是否安裝了MS XML Parser運行庫!");return wvarQuery;}// 根節點的名稱為vjournal// 建立元素並添加到文檔中xmlRoot = pDoc->createElement("vjournal");pDoc->appendChild(xmlRoot);IXMLDOMElementPtr pNode;// 添加“tags”元素pNode = pDoc->createElement("tags");pNode->Puttext((const char *)"bad");xmlRoot->appendChild(pNode);// 添加“dtstart”元素pNode = pDoc->createElement("dtstart");pNode->Puttext((const char *)"2009-02-25T10:01:19.933723Z");xmlRoot->appendChild(pNode);// 添加“description”元素pNode = pDoc->createElement("description");pNode->Puttext((const char *)"1");xmlRoot->appendChild(pNode);// 儲存到檔案,如果存在就覆蓋,否則不存在就建立.// 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("無法建立DOMDocument對象,請檢查是否安裝了MS XML Parser 運行庫!");        return ;    }        // 負載檔案    // pDoc->load("test.xml");    // 載入記憶體    pDoc->loadXML(bstXML);long lChilds, i;// 根節點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++)    {        IXMLDOMNodePtr pNode = pNodeList->Getitem(i);// 過濾注釋節點if (pNode->GetnodeType() != NODE_COMMENT){BSTR bstrNodeName = pNode->GetnodeName();char *lpszNodeName = _com_util::ConvertBSTRToString(bstrNodeName);strncpy(szNodeName, lpszNodeName, sizeof(szNodeName));delete []lpszNodeName;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;        // 如果要向伺服器post資料,這個地方一定要設定為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;         // 處理返回的xml資料,對返回的xml資料進行解析,主要是dom方法.         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 *lpszBody = _com_util::ConvertBSTRToString(bstrbody);// 這裡將顯示WebServer body區的資料“Hello SystematICS!”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;}

六、測試

1)、HTTP CLIENT發送:

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>

 

注意:文本最後是“\r\n\r\n”兩個斷行符號換行結束。

2)、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>

 

注意:文本最後是“\r\n\r\n”兩個斷行符號換行結束。

3)、HTTP SERVER響應:
"HTTP/1.1 200 OK\r\nContent-Length:0\r\n\r\n"

即:

HTTP/1.1 200 OK

Content-Length:0

 

注意:文本最後是“\r\n\r\n”兩個斷行符號換行結束。長度為0表示BODY為空白字串。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.