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

HTTP服务端JSON服务端的更多相关文章

  1. 在CentOS7服务器端启动jupyter notebook服务,在windows端使用jupyter notebook,服务器充当后台计算云端

    在CentOS7服务器端启动jupyter notebook服务,在windows端使用jupyter notebook,服务器充当后台计算云端 在服务器端启动jupyter notebook服务,在 ...

  2. Dubbo学习笔记2:Dubbo服务提供端与消费端应用的搭建

    Demo结构介绍 Demo使用Maven聚合功能,里面有三个模块,目录如下: 其中Consumer模块为服务消费者,里面TestConsumer和consumer.xml组成了基于Spring配置方式 ...

  3. 二、eureka服务端注册服务

    所有文章 https://www.cnblogs.com/lay2017/p/11908715.html 正文 入口 上文我们说到,eureka是使用jersey来对外提供restful风格的rpc调 ...

  4. 【.NET6】gRPC服务端和客户端开发案例,以及minimal API服务、gRPC服务和传统webapi服务的访问效率大对决

    前言:随着.Net6的发布,Minimal API成了当下受人追捧的角儿.而这之前,程序之间通信效率的王者也许可以算得上是gRPC了.那么以下咱们先通过开发一个gRPC服务的教程,然后顺势而为,再接着 ...

  5. 在Android中调用KSOAP2库访问webservice服务出现的服务端传入参数为null的问题解决

    ksoap2-android-3.0.0-jar 第三方库来调用.net 写的Web Service 如果没有参数,那么调用一切顺利,但是如果服务是带参数的,那么服务端接收的参数都是nul.      ...

  6. 微服务学习三:springboot与springcloud集成之Eurake的使用(server端,client端)

    这个多亏了网站上的一个大神的博客: http://blog.csdn.net/forezp/article/details/70148833 强烈推荐学习: 1.springcloud是什么,这个大家 ...

  7. 恩布企业IM PC端,服务端公布 1.16 版本号

    恩布企业IM PC端,服务端公布1.16版本号,开源企业IM.免费企业即时通讯软件:主要版本号更新内容: 恩布服务端核心程序,添加进程守护保护机制,确保系统7*24持续稳定服务: 服务端添加内存数据库 ...

  8. 【转】京东金融App端链路服务端全链路压测策略

    京东金融移动端全链路压测历时三个月,测试和服务端同学经过无数日日夜夜,通宵达旦,终于完成了移动端链路的测试任务.整个测试有部分涉及到公司敏感数据,本文只对策略部分进行论述. 1.系统架构与策略 在聊性 ...

  9. zabbix配置文件详解--服务(server)端、客户(agent)端、代理(proxy)端

    在zabbix服务(server)端.客户(agent)端.代理(proxy)端分别对应着一个配置文件,即:zabbix_server.conf,zabbix_agentd.conf,zabbix_p ...

随机推荐

  1. html5——3D案例(立方体)

    立方体:父盒子规定了3d呈现属性,立方体做旋转运动 移动顺序:1.每个盒子都先移动100px,然后再做相应的旋转  2.只有这样立方体的几何中心点与父盒子的几何中心点是一样的 <!DOCTYPE ...

  2. Java中的方法重写

    方法的重载: 在同一个类中,出现多个同名的方法,参数列表不同,与返回值类型,修饰符无关 方法的重写: 子类中出现和父类中一模一样的方法(包括返回值类型,方法名,参数列表) 方法重写的注意事项: 1.重 ...

  3. ThinkPHP框架表单验证AJAX

    验证有两种方式:静态验证与动态验证. 一.静态验证 在模型类里面预先定义好该模型的自动验证规则,我们称为静态定义. 验证时要在test表的Model里面加验证条件:新建testModel.class. ...

  4. js 字符串,数组扩展

    console.log(Array.prototype.sort)//ƒ substring() { [native code] } console.log(String.prototype.subs ...

  5. forcedirectories和CreateDirectory

    forcedirectories和CreateDirectory都能创建文件ForceDirectories可以创建多层目录. 如果你创建一个目录为c:\mymusic\music 如果你的C盘不存在 ...

  6. php第十八节课

    PDO 对不同的数据库连接使用 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht ...

  7. Linux之网络ping(unknown host)故障及yum no more mirrors to try

    1.ping外网出现ping:unknown host   字样故障 鉴于网上大多都是提供临时生效的解决办法,这里不再赘述,并提供下永久生效的方案: 永久生效: 1)添加DNS地址和下一跳网关地址至网 ...

  8. python 列出出当前目录及所有子目录下的文件

    [root@web1 test]# cat walk.py #!/usr/bin/python # -*- coding: UTF-8 -*- import os for root, dirs, fi ...

  9. webstorm下ES6转ES5

    ECMAScript 6是JavaScript语言的下一代标准,已经在2015年6月正式发布了.Mozilla公司将在这个标准的基础上,推出JavaScript 2.0. ES6的目标,是使得Java ...

  10. springcloud(四):Eureka客户端公共组件打包方式

    ,      一.前言  各位大佬应该知道,在大型项目中都需要有数据传输层,一般项目都采用的是MVC结构,如果有10个表,则会创建10个实体类,在各个层之间应该使用实体类传递数据: 在微服架构中,也许 ...