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:\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文件,源代码清单如下

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

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

  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”的错误。

服务端代码

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

测试服务端代码的html源码

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

configure.js代码

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

最新文章

  1. linux ssh config
  2. c语言内存对齐问题
  3. Linux Shell 03 条件测试
  4. Spark metrics on wordcount example
  5. 叉积判断 POJ1696
  6. IPMITOOL常用操作指令
  7. codeforces 3D . Least Cost Bracket Sequence 贪心
  8. B桥接模式ridge
  9. UVa 10179 - Irreducable Basic Fractions
  10. fir.im Weekly - 2017 年必须了解的 iOS 开源库
  11. xml和java对象互转:JAXB注解的使用详解
  12. EOJ Monthly 2018.7 B.锐角三角形(数学几何+思维)
  13. 在ubuntu server上搭建Hadoop
  14. build high performance server 转载
  15. Javascript 知识遗漏点梳理。
  16. 解决「matplotlib 图例中文乱码」问题
  17. a链接传参的方法
  18. CodeForces 740C Alyona and mex
  19. SpringMVC Controller 介绍(详细深刻)
  20. 【译】常见 Java 异常解释(恶搞版)

热门文章

  1. SPA设计架构
  2. [Windows Server 2003] IIS自带FTP安装及配置方法
  3. C# 时间对比
  4. windons共享的一些问题
  5. includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。
  6. 破解js中的this指向
  7. PostgreSQL使用总结
  8. Scrapy实战:使用scrapy再再次爬取干货集中营的妹子图片
  9. 三、Scrapy中选择器用法
  10. linux 头文件和库文件的设置