zoukankan      html  css  js  c++  java
  • HTTP服务端JSON服务端

    HTTP服务端JSON服务端

    最后更新日期:  2014-5-18

    Author: Kagula

    阅读前提: CMake工具的基本使用

    内容简介:

       CPPCMS是个开源Web开发框架,通过它可以很容易实现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:SDKzlib-1.2.8uild;

    库文件位置:D:/SDK/zlib-1.2.8/build/Release

    openssl

    头文件位置:D:SDKopenssl-1.0.1ginclude

    库文件位置:D:SDKopenssl-1.0.1gout32dll

    icu4c

             下载http://download.icu-project.org/files/icu4c/53.1/icu4c-53_1-src.zip文件

    打开D:SDKicu4c-53_1-srcicusourceallinoneallinone.sln文件,Build出Release版本即可。

    头文件位置:D:SDKicu4c-53_1-srcicuinclude

    库文件位置:;D:SDKicu4c-53_1-srciculib

    pcre

             下载ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.35.zip

             使用CMake工具在D:SDKpcre-8.35uild下生成PCRE.sln文件,使用VisualStudio 2013打开并编译即可。

    头文件位置:D:/SDK/pcre-8.35;D:SDKpcre-8.35uild;

    库文件位置:D:SDKpcre-8.35uildRelease

    准备好后就可以构建cppcms库了

    从cppcms官网下载cppcms-1.0.4.tar.bz2文件并解压缩到“D:SDKcppcms-1.0.4”,打开cmake gui工具configure后,出现了很多变量

    添加变量

    CMAKE_INCLUDE_PATH

    类型为filepath

    值为

    D:/SDK/pcre-8.35;D:SDKpcre-8.35uild;D:/SDK/zlib-1.2.8;D:SDKzlib-1.2.8uild;D:SDKicu4c-53_1-srcicuinclude;D:SDKopenssl-1.0.1ginclude

    添加变量

    CMAKE_LIBRARY_PATH

    类型为filepath

    值为D:SDKpcre-8.35uildRelease;D:/SDK/zlib-1.2.8/build/Release;D:SDKicu4c-53_1-srciculib;D:SDKopenssl-1.0.1gout32dll;C:ProgramFiles (x86)Microsoft SDKsWindowsv7.1ALib

             重新configure后generate。打开新生成的sln文件。BuildSolution有四个选项Debug、MinSizeRel(最小发行版)、Release、RelWithDebInfo(带Debug信息的发行版),我们这里选Release模式build。

    编译过程中碰到

    [1]zconf.h文件找不到的问题,这个文件在我的D:SDKzlib-1.2.8uild路径下,给它地址,这个问题解决。

    [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:SDKcppcms-1.0.4oosterooster owidefstream.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:SDKcppcms-1.0.4cppcmsapplication.h”文件第298行

    virtual void main(std::string url);

    修改为

    virtual void main(const char* url);

    [5-2]“D:SDKcppcms-1.0.4srcapplication.cpp”文件第200行

    void application::main(std::string  url)

    修改为

    void application::main(const char* url)

    [5-3]“D:SDKcppcms-1.0.4srcurl_dispatcher.cpp”文件第49行

    [6]修改json_rpc_server相关文件,使json服务可用

    [6-1]

    “D:SDKcppcms-1.0.4cppcms pc_json.h”152行

    virtual void main(std::string);

    改为

    virtual void main(const char*);

     [6-2]“D:SDKcppcms-1.0.4src pc_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.4uildRelease目录下可以找到。

             下面我们用CPPCMS写一个HelloWorld程序

    Hello World

        构建我们的第一个例子时使用了boost库用来把GBK字符串转utf字符串,我计算机的boost库安装路径是“D:SDKoost_1_55_0”。

             在Visual Studio中新建Win32 控制台项目,AdditonalOptions选项Empty Project。

    设置头文件搜索路径

    D:SDKcppcms-1.0.4

    D:SDKcppcms-1.0.4uild

    D:SDKcppcms-1.0.4ooster

    D:SDKcppcms-1.0.4uildooster

    D:SDKoost_1_55_0

    设置库文件搜索路径

    D:SDKcppcms-1.0.4uildoosterRelease

    D:SDKcppcms-1.0.4uildRelease

    D:SDKoost_1_55_0stagelib

    添加链接库cppcms.lib

    复制下面7个动态链接库到你项目文件夹中,否则会提示找不到这些DLL文件

    D:SDKpcre-8.35uildReleasepcre.dll

    D:SDKzlib-1.2.8uildReleasezlib.dll

    D:SDKcppcms-1.0.4uildReleasecppcms.dll

    D:SDKcppcms-1.0.4uildoosterReleaseooster.dll

    D:SDKicu4c-53_1-srcicuinicuuc53.dll

    D:SDKicu4c-53_1-srcicuinicudt53.dll

    D:SDKicu4c-53_1-srcicuinicuin53.dll

    添加Source.cpp文件,源代码清单如下

    [cpp] view plain copy
     
    1. #include <cppcms/application.h>  
    2. #include <cppcms/applications_pool.h>  
    3. #include <cppcms/service.h>  
    4. #include <cppcms/http_response.h>  
    5.   
    6. #include <boost/locale.hpp>  
    7.   
    8. class hello : public cppcms::application {  
    9. public:  
    10.     hello(cppcms::service &srv) :  
    11.         cppcms::application(srv)  
    12.     {  
    13.     }  
    14.     void main(const char* url);  
    15. };  
    16.   
    17. void hello::main(const char* url)  
    18. {  
    19.     //GBK转utf  
    20.     std::string  utfStr =   
    21.         boost::locale::conv::to_utf<char>("<h1>中文测试</h1> ", "GBK");  
    22.   
    23.     //输出  
    24.     response().out() <<  
    25.         "<html> "  
    26.         "<body> "  
    27.         <<utfStr<<  
    28.         "</body> "  
    29.         "</html> ";  
    30. }  
    31.   
    32.   
    33. int main(int argc, char ** argv)  
    34. {  
    35.     try  
    36.     {  
    37.         /* 
    38.         命令行参数为 -c configure.js 
    39.         让CPPCMS读取configure.js里我们的配置信息 
    40.         */  
    41.         cppcms::service srv(argc, argv);  
    42.   
    43.         //挂载用户的Web服务,application的继承类hello  
    44.         srv.applications_pool().mount(cppcms::applications_factory<hello>());  
    45.   
    46.         //这里阻塞,等待用户请求  
    47.         srv.run();  
    48.     }  
    49.     catch (std::exception const &e)  
    50.     {  
    51.         std::cerr << e.what() << std::endl;  
    52.     }  
    53. }  

    添加configure.js文件,源代码清单如下

    [javascript] view plain copy
     
    1. {    
    2.     "service" : {    
    3.         "api" : "http",    
    4.         "port" : 8080    
    5.     },    
    6.     "http" : {    
    7.         "script_names" : [ "/hello" ]    
    8.     }    
    9. }    

    按[F5]以Debug方式运行即可。

    现在你可以使用http://localhost:8080/这个地址访问你的HTTP服务器了。

    JSon服务器例子

             我测试了下面这个链接中贴出的代码,可以用,但是如果你的测试程序是在Debug模式,你只能调用debug模式编译出来的CPPCMS动态库,如果你是在Release模式,就只能调用Release模式编译出来的CPPCMS动态库,否则会抛出“bad allocation”的错误。

     服务端代码

    [cpp] view plain copy
     
    1. #include <cppcms/application.h>  
    2. #include <cppcms/applications_pool.h>  
    3. #include <cppcms/service.h>  
    4. #include <cppcms/http_response.h>  
    5. #include <cppcms/rpc_json.h>  
    6. #include <cppcms/json.h>  
    7. #include <cppcms/mount_point.h>  
    8. #include <map>  
    9. #include <string>  
    10.   
    11. #include <exception>  
    12. #include <iostream>  
    13.   
    14. /* 
    15. 标题:测试CPPCMS提供的JSON_RPC服务功能 
    16. 来源: 
    17. 使用cppcms开发JSON_RPC服务 
    18. http://www.zeuux.com/group/candcplus/bbs/content/55785/ 
    19.  
    20. */  
    21. using namespace std;  
    22. using cppcms::rpc::json_rpc_server;  
    23. using cppcms::rpc::json_method;  
    24.   
    25. class calc_service : public json_rpc_server {  
    26. public:  
    27.     calc_service(cppcms::service &srv) : json_rpc_server(srv) {  
    28.         bind("sum",  
    29.             json_method(&calc_service::sum, this), method_role);  
    30.         bind("div",  
    31.             json_method(&calc_service::div, this), method_role);  
    32.     }  
    33.     void sum(int x, int y) {  
    34.         cppcms::json::value v;  
    35.         v["x"] = x;  
    36.         v["y"] = y;  
    37.         v["result"] = x + y;  
    38.         return_result(v);  
    39.     }  
    40.     void div(int x, int y) {  
    41.         if (y == 0) {  
    42.             return_error("Division by zero.");  
    43.         }  
    44.         else {  
    45.             return_result(x / y);  
    46.         }  
    47.     }  
    48. };  
    49.   
    50. class hello_service : public json_rpc_server {  
    51. public:  
    52.     hello_service(cppcms::service &srv) : json_rpc_server(srv) {  
    53.         bind("hello",  
    54.             json_method(&hello_service::hello, this), method_role);  
    55.         bind("hello_all",  
    56.             json_method(&hello_service::hello_all, this), method_role);  
    57.         bind("hello_x",  
    58.             json_method(&hello_service::hello_x, this), method_role);  
    59.     }  
    60.     void hello(string name) {  
    61.         string say = "Hello, " + name + ".";  
    62.         return_result(say);  
    63.     }  
    64.     void hello_all(vector<string> names) {  
    65.         string say = "Hello, ";  
    66.         for (unsigned i = 0; i<names.size(); i++) {  
    67.             say += names[i] + " ";  
    68.         }  
    69.         return_result(say);  
    70.     }  
    71.     void hello_x(cppcms::json::value val) {  
    72.         return_result(val);  
    73.     }  
    74. };  
    75.   
    76. int main(int argc, char ** argv)  
    77. {  
    78.     try {  
    79.         cppcms::service srv(argc, argv);  
    80.   
    81.         srv.applications_pool().mount(  
    82.             cppcms::applications_factory<calc_service>(),  
    83.             cppcms::mount_point("/calc")  
    84.             );  
    85.   
    86.         srv.applications_pool().mount(  
    87.             cppcms::applications_factory<hello_service>(),  
    88.             cppcms::mount_point("/hello")  
    89.             );  
    90.         srv.run();  
    91.     }  
    92.     catch (exception const &e) {  
    93.         cerr << e.what() << endl;  
    94.     }  
    95.     return 0;  
    96. }  



    测试服务端代码的html源码

    [cpp] view plain copy
     
    1. <html>  
    2. <body>  
    3.     <script type="text/javascript">  
    4.         function call() {  
    5.   
    6.             var xhr = new XMLHttpRequest();  
    7.             xhr.open("post", 'http://localhost:8080/calc');  
    8.             // Required by JSON-RPC over HTTP  
    9.             xhr.setRequestHeader("Content-Type", "application/json");  
    10.   
    11.             // It is better to use real formatter like JSON.js  
    12.             x = parseInt(document.getElementById('x').value);  
    13.             y = parseInt(document.getElementById('y').value);  
    14.             var request = '{"method":"div","params":[' + x + ',' + y + '],"id":1}';  
    15.   
    16.             xhr.onreadystatechange = function () {  
    17.                 if (xhr.readyState === 4) {  
    18.                     res = 'Unknown Error';  
    19.                     if (xhr.status === 200) {  
    20.                         // Don't call eval in real code use some parser  
    21.                         var result = eval('(' + xhr.responseText + ')');  
    22.                         if (result.error == null) {  
    23.                             res = result.result;  
    24.                         }  
    25.                         else {  
    26.                             res = result.error;  
    27.                         }  
    28.                     }  
    29.                     document.getElementById('result').innerHTML = res;  
    30.                 }  
    31.             }  
    32.             xhr.send(request);  
    33.             return false;  
    34.         }  
    35.     </script>  
    36.     <form onsubmit="return call();">  
    37.         <p>  
    38.             <input type="text" id="x" />  
    39.             <input type="submit" value="/" />  
    40.             <input type="text" id="y" /> =  
    41.             <span id="result"></span>  
    42.         </p>  
    43.     </form>  
    44. </body>  
    45. </html>  


    configure.js代码

    [javascript] view plain copy
     
    1. {  
    2.     "service" : {  
    3.         "api" : "http",  
    4.         "port" : 8080,  
    5.         },  
    6.     "http" : {  
    7.         "script_names" : [ "/calc","/hello" ]  
    8.     }  
    9. }  

    补充阅读资料

    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技术。

  • 相关阅读:
    C# Linq 交集、并集、差集、去重
    SpringICO和DI区别
    postman调用webapi错误记录
    NetCore实例提供的依赖注入的生命周期
    ios处理暴力输出问题
    一块国外开源的视频播发器
    一个有创意的3D APP
    Flurry Analytics最近免费添加了获取新用户分析和app崩溃报告的功能
    那些域名服务商
    Moneybookers的优点
  • 原文地址:https://www.cnblogs.com/lidabo/p/7155097.html
Copyright © 2011-2022 走看看