標籤:系統 detail rdp signed utf8 software download submit uil
HTTP服務端JSON服務端
最後更新日期: 2014-5-18
Author: Kagula
閱讀前提: CMake工具的基本使用
內容簡單介紹:
CPPCMS是個開源Web開發架構,通過它能夠非常easy實現HTTP服務和JSON服務,這裡介紹CPPCMS開發環境的搭建。寫一個CPPCMS測試程式,它建立HTTP服務,向瀏覽器返回Hello,World頁面。CPPCMS依賴的一些第三方庫,其他地方已經介紹怎麼Build,所以這裡不反覆了。
環境:Windows8.1 64bit、Visual Studio 2013 Professional SP1
zlib-1.2.8、openssl-1.0.1g、pcre-8.35、icu4c-53_1、 cppcms-1.0.4、python-3.4.0.、CMake2.8.12.2、
boost 1.55
搭建CPPCMS開發環境
CPPCMS依賴zlib、openssl、pcre、icu4c、python和Win SDK等第三方庫或工具
在python官網下載、安裝python-3.4.0.amd64.msi,不要忘記在嚮導中勾選,把python.exe的位置增加到系統的環境變數中。
我電腦中編譯好的庫,它們的位置
zlib
標頭檔位置:D:/SDK/zlib-1.2.8;D:\SDK\zlib-1.2.8\build;
庫檔案位置:D:/SDK/zlib-1.2.8/build/Release
openssl
標頭檔位置:D:\SDK\openssl-1.0.1g\include
庫檔案位置:D:\SDK\openssl-1.0.1g\out32dll
icu4c
下載http://download.icu-project.org/files/icu4c/53.1/icu4c-53_1-src.zip檔案
開啟D:\SDK\icu4c-53_1-src\icu\source\allinone\allinone.sln檔案。Build出Release版本號碼就可以。
標頭檔位置:D:\SDK\icu4c-53_1-src\icu\include
庫檔案位置:;D:\SDK\icu4c-53_1-src\icu\lib
pcre
下載ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.35.zip
使用CMake工具在D:\SDK\pcre-8.35\build\下產生PCRE.sln檔案。使用VisualStudio 2013開啟並編譯就可以。
標頭檔位置:D:/SDK/pcre-8.35;D:\SDK\pcre-8.35\build;
庫檔案位置:D:\SDK\pcre-8.35\build\Release
準備好後就能夠構建cppcms庫了
從cppcms官網下載cppcms-1.0.4.tar.bz2檔案並解壓縮到“D:\SDK\cppcms-1.0.4”,開啟cmake gui工具configure後,出現了非常多變數
加入變數
CMAKE_INCLUDE_PATH
類型為filepath
值為
D:/SDK/pcre-8.35;D:\SDK\pcre-8.35\build;D:/SDK/zlib-1.2.8;D:\SDK\zlib-1.2.8\build;D:\SDK\icu4c-53_1-src\icu\include;D:\SDK\openssl-1.0.1g\include
加入變數
CMAKE_LIBRARY_PATH
類型為filepath
值為D:\SDK\pcre-8.35\build\Release;D:/SDK/zlib-1.2.8/build/Release;D:\SDK\icu4c-53_1-src\icu\lib;D:\SDK\openssl-1.0.1g\out32dll;C:\ProgramFiles (x86)\Microsoft SDKs\Windows\v7.1A\Lib
又一次configure後generate。開啟新產生的sln檔案。BuildSolution有四個選項Debug、MinSizeRel(最小發行版)、Release、RelWithDebInfo(帶Debug資訊的發行版)。我們這裡選Release模式build。
編譯過程中碰到
[1]zconf.h檔案找不到的問題,這個檔案在我的D:\SDK\zlib-1.2.8\build路徑下,給它地址,這個問題解決。
[2]json.cpp 檔案 return is_ 程式碼通只是, 改為returnbool(is_)就可以,由於Visual Studio 2013(C++11標準)要求istream顯式(explicitly)轉換bool類型。
[3]test_formatting.cpp和test_boundary.cpp原始碼檔案由於出現特殊字元(事實上是檔案語言編碼的問題)導致無法編譯。跳過,由於這兩個測試項目不能編譯,不影響我們以後使用cppcms庫。
[4]改動D:\SDK\cppcms-1.0.4\booster\booster\nowide\fstream.h檔案第44行,
if(my_base_type::open(convert(s).c_str(),mode)){
改動為
if (std::basic_filebuf<CharType,Traits>::open(s, mode)) {
否則調用CPPCMS的Debug版會掛掉。
[5]因為CPPCMS的Release版本號碼application類的main方法std::string實參釋放時會出錯,所以我把它改成const char *類型。以下三步是詳細步驟
[5-1]“D:\SDK\cppcms-1.0.4\cppcms\application.h”檔案第298行
virtual void main(std::string url);
改動為
virtual void main(const char* url);
[5-2]“D:\SDK\cppcms-1.0.4\src\application.cpp”檔案第200行
void application::main(std::string url)
改動為
void application::main(const char* url)
[5-3]“D:\SDK\cppcms-1.0.4\src\url_dispatcher.cpp”檔案第49行
[6]改動json_rpc_server相關檔案。使json服務可用
[6-1]
“D:\SDK\cppcms-1.0.4\cppcms\rpc_json.h”152行
virtual void main(std::string);
改為
virtual void main(const char*);
[6-2]“D:\SDK\cppcms-1.0.4\src\rpc_json.cpp”148行
void json_rpc_server::main(std::string/*unused*/)
改為
void json_rpc_server::main(const char*/*unused*/)
app_->main(match_[select_]);
改動為
std::string tmp = match_[select_];
app_->main(tmp.c_str());
如今rebuild整個solution, 等待幾分鐘後,Visual studio 2013提示77個成功,2個失敗(剛才說的檔案語言編碼問題),3個跳過。這樣就能夠了。Build後的cppcms.dll、cppcms.lib檔案在...\cppcms-1.0.4\build\Release檔案夾下能夠找到。
以下我們用CPPCMS寫一個HelloWorld程式
Hello World
構建我們的第一個範例時使用了boost庫用來把GBK字串轉utf字串,我電腦的boost庫安裝路徑是“D:\SDK\boost_1_55_0”。
在Visual Studio中建立Win32 控制台項目,AdditonalOptions選項Empty Project。
設定標頭檔搜尋路徑
D:\SDK\cppcms-1.0.4
D:\SDK\cppcms-1.0.4\build
D:\SDK\cppcms-1.0.4\booster
D:\SDK\cppcms-1.0.4\build\booster
D:\SDK\boost_1_55_0
設定庫檔案搜尋路徑
D:\SDK\cppcms-1.0.4\build\booster\Release
D:\SDK\cppcms-1.0.4\build\Release
D:\SDK\boost_1_55_0\stage\lib
加入連結庫cppcms.lib
複製以下7個動態連結程式庫到你項目目錄中。否則會提示找不到這些DLL檔案
D:\SDK\pcre-8.35\build\Release\pcre.dll
D:\SDK\zlib-1.2.8\build\Release\zlib.dll
D:\SDK\cppcms-1.0.4\build\Release\cppcms.dll
D:\SDK\cppcms-1.0.4\build\booster\Release\booster.dll
D:\SDK\icu4c-53_1-src\icu\bin\icuuc53.dll
D:\SDK\icu4c-53_1-src\icu\bin\icudt53.dll
D:\SDK\icu4c-53_1-src\icu\bin\icuin53.dll
加入Source.cpp檔案。源碼清單例如以下
#include <cppcms/application.h>#include <cppcms/applications_pool.h>#include <cppcms/service.h>#include <cppcms/http_response.h>#include <boost/locale.hpp>class hello : public cppcms::application {public:hello(cppcms::service &srv) :cppcms::application(srv){}void main(const char* url);};void hello::main(const char* url){//GBK轉utfstd::string utfStr = boost::locale::conv::to_utf<char>("<h1>中文測試</h1>\n", "GBK");//輸出response().out() <<"<html>\n""<body>\n"<<utfStr<<"</body>\n""</html>\n";}int main(int argc, char ** argv){try{/*命令列參數為 -c configure.js讓CPPCMS讀取configure.js裡我們的配置資訊*/cppcms::service srv(argc, argv);//掛載使用者的Web服務,application的繼承類hellosrv.applications_pool().mount(cppcms::applications_factory<hello>());//這裡堵塞。等待使用者請求srv.run();}catch (std::exception const &e){std::cerr << e.what() << std::endl;}}
加入configure.js檔案,源碼清單例如以下
{ "service" : { "api" : "http", "port" : 8080 }, "http" : { "script_names" : [ "/hello" ] } }
按[F5]以Debug方式執行就可以。
如今你能夠使用http://localhost:8080/這個地址訪問你的HTTPserver了。
JSonserver範例
我測試了以下這個連結中貼出的代碼,能夠用,可是假設你的測試程式是在Debug模式,你僅僅能調用debug模式編譯出來的CPPCMS動態庫,假設你是在Release模式。就僅僅能調用Release模式編譯出來的CPPCMS動態庫。否則會拋出“bad allocation”的錯誤。
服務端代碼
#include <cppcms/application.h>#include <cppcms/applications_pool.h>#include <cppcms/service.h>#include <cppcms/http_response.h>#include <cppcms/rpc_json.h>#include <cppcms/json.h>#include <cppcms/mount_point.h>#include <map>#include <string>#include <exception>#include <iostream>/*標題:測試CPPCMS提供的JSON_RPC服務功能來源:使用cppcms開發JSON_RPC服務http://www.zeuux.com/group/candcplus/bbs/content/55785/*/using namespace std;using cppcms::rpc::json_rpc_server;using cppcms::rpc::json_method;class calc_service : public json_rpc_server {public:calc_service(cppcms::service &srv) : json_rpc_server(srv) {bind("sum",json_method(&calc_service::sum, this), method_role);bind("div",json_method(&calc_service::div, this), method_role);}void sum(int x, int y) {cppcms::json::value v;v["x"] = x;v["y"] = y;v["result"] = x + y;return_result(v);}void div(int x, int y) {if (y == 0) {return_error("Division by zero.");}else {return_result(x / y);}}};class hello_service : public json_rpc_server {public:hello_service(cppcms::service &srv) : json_rpc_server(srv) {bind("hello",json_method(&hello_service::hello, this), method_role);bind("hello_all",json_method(&hello_service::hello_all, this), method_role);bind("hello_x",json_method(&hello_service::hello_x, this), method_role);}void hello(string name) {string say = "Hello, " + name + ".";return_result(say);}void hello_all(vector<string> names) {string say = "Hello, ";for (unsigned i = 0; i<names.size(); i++) {say += names[i] + " ";}return_result(say);}void hello_x(cppcms::json::value val) {return_result(val);}};int main(int argc, char ** argv){try {cppcms::service srv(argc, argv);srv.applications_pool().mount(cppcms::applications_factory<calc_service>(),cppcms::mount_point("/calc"));srv.applications_pool().mount(cppcms::applications_factory<hello_service>(),cppcms::mount_point("/hello"));srv.run();}catch (exception const &e) {cerr << e.what() << endl;}return 0;}
測試服務端代碼的html原始碼
<html><body> <script type="text/javascript"> function call() { var xhr = new XMLHttpRequest(); xhr.open("post", ‘http://localhost:8080/calc‘); // Required by JSON-RPC over HTTP xhr.setRequestHeader("Content-Type", "application/json"); // It is better to use real formatter like JSON.js x = parseInt(document.getElementById(‘x‘).value); y = parseInt(document.getElementById(‘y‘).value); var request = ‘{"method":"div","params":[‘ + x + ‘,‘ + y + ‘],"id":1}‘; xhr.onreadystatechange = function () { if (xhr.readyState === 4) { res = ‘Unknown Error‘; if (xhr.status === 200) { // Don‘t call eval in real code use some parser var result = eval(‘(‘ + xhr.responseText + ‘)‘); if (result.error == null) { res = result.result; } else { res = result.error; } } document.getElementById(‘result‘).innerHTML = res; } } xhr.send(request); return false; } </script> <form onsubmit="return call();"> <p> <input type="text" id="x" /> <input type="submit" value="/" /> <input type="text" id="y" /> = <span id="result"></span> </p> </form></body></html>
configure.js代碼
{ "service" : { "api" : "http", "port" : 8080, }, "http" : { "script_names" : [ "/calc","/hello" ] }}
補充閱讀資料
CPPCMS在Linux下的編譯和安裝
http://blog.csdn.net/csfreebird/article/details/6730623
官網的Hello World範例
http://cppcms.com/wikipp/en/page/cppcms_1x_tut_hello
深入學習 CppCMS
http://remonstrate.wordpress.com/2012/04/09/%E6%B7%B1%E5%85%A5%E5%AD%A6%E4%B9%A0-cppcms/
CppCMS和Nginx協同工作
http://www.cnblogs.com/believeit/archive/2011/09/03/2183531.html
CppCMS支援檔案上傳
http://www.oschina.net/question/565065_66895
boost庫學習隨記五 Boost.Locale 之字元轉換 gbkutf8 big5 string wstring等
http://blog.csdn.net/leitianjun/article/details/24658655
How to Build libiconv with Microsoft VisualStudio
http://www.codeproject.com/Articles/302012/How-to-Build-libiconv-with-Microsoft-Visual-Studio
注意,IE6不支援JSON_RPC技術。
HTTP服務端JSON服務端