2013年3月23日星期六

理工科应该的知道的C/C++数学计算库(转)

理工科应该的知道的C/C++数学计算库(转)

作为理工科学生,想必有限元分析、数值计算、三维建模、信号处理、性 能分析、仿真分析。。。这些或多或少与我们常用的软件息息相关,假如有一天你只需要这些大型软件系统的某一个很有限的功能,你是不是也要因此再用一用那动 辄几个g的软件呢?其实我觉得如果系统不是很大,不是很复杂,我们个人完全有可能自己去编写代码来实现这些‘’有限的功能‘’。别以为这是件很困难的事 情,我总以为大学期间学的c语言是极其有用的,只要你会基本的c语言语法,你就可以的。
     下面我来介绍几个非常有益的c/c++数学计算库,他们基本上都是开源的,你完全不必担心版权问题,他们都是一些自由软件,你要做的仅仅是仔细阅读他们的授权协议确保不要滥用就可以了:
 计算几何算法库 CGAL
CGAL ,计算几何算法库,是一个大型C + +库的几何数据结构和算法,如Delaunay三角网,网格生成,布尔运算的多边形,以及各种几何处理算法。 CGAL是用来在各个领域:计算机图形学,科学可视化,计算机辅助设计与建模,地理信息系统,分子生物学,医学影像学,机器人学和运动规划,和数值方法。
下载网址 http://www.cgal.org/download.html
 数学软件包 Octave
 Octave 是一个类似matlab和Scilab的数学软件包,可以进行各种运算,编程。它还有丰富的C++接口可以让用户编程时调用。它绘图使用gnuplot。
Octave的使用也是基于字符终端模式的,当需要绘图时,将会调用Gnuplot进行数据绘图,并显示出来。
Octave是用C++编写的,它内容丰富的库也可以供用户在编写软件时调用。Octave库的详细介绍在/usr/share/doc/octave-2.1.50/liboctave下,文件是liboctave.dvi,需要PDF文件的,可以运行:
 dvipdfm liboctave.dvi
将dvi文件转换为PDF文件。
Octave同时还支持Fortran等的调用,GSL绑定等。可以由用户定制自己的函数、子程序等。
下载地址  http://octave.sourceforge.net/packages.html
C++ 数学计算库 TooN
TooN 是一个C++ 数学计算库,其目的是有效运作的大量小型矩阵,并提供方便一些算法包括矩阵分解和优化。
下载地址http://mi.eng.cam.ac.uk/~er258/cvd/toon/html-user/index.html
有限元分析软件 OpenFEM
有 限元分析,即使用有限元方法来分析静态或动态的物体或系统。在这种方法中一个物体或系统被分解为由多个相互联结的、简单、独立的点组成的几何模型。在这 种方法中这些独立的点的数量是有限的,因此被称为有限元。由实际的物理模型中推导出来得平衡方程式被使用到每个点上,由此产生了一个方程组。这个方程组可 以用线性代数的方法来求解。有限元分析的精确度无法无限提高。元的数目到达一定高度后解的精确度不再提高,只有计算时间不断提高。
下载地址 http://sourceforge.net/projects/openfem/files/
有限元计算框架 OOFEM
OOFEM 是一个开源多物理并行有限元程序的面向对象的架构。这个项目的目的是提供高效率和强大的有限元计算工具,以及提供高度模块化和可扩展性的发展环境。有限元 分析通常借助计算机软件完成,著名工程软件有:MSC.Nastran、ADINA、LS-DYNA、ANSYS、ABAQUS、2D-sigma等。
下载地址  http://www.oofem.org/en/download/download.html
C++符号计算库 GiNaC
GiNaC(GiNaC 不是一个 CAS 计算机代数系统))是一个用于符号计算的C++库。它的设计允许集成系统创造,象征性的操作嵌入与更成熟的计算机科学(如计算密集型,图形界面等),数字 应用领域。相对于其他情况下,它不会尝试代数提供广泛的功能和简单的编程语言,而是接受一个给定语言(C + +)和扩展了代数功能设置。
下载地址 http://www.ginac.de/Download.html
类C的数学专用语言EngLabEngLab是一个类C的数学专用语言。它语法简单,关键字很少,工程师和那些只会少许编程知识的人便能很好的掌握。
下载地址http://sourceforge.net/projects/englab/files/
C++信号处理库 SP++
TSPL(Template Signal Processing Library) 是一个 C++ 的信号处理库,主要包括滤波器设计、时频分析和小波变换,同时还包含一些关于向量和矩阵的基本算法,所有的算法基于 C++ 模板类编写而成。
下载地址http://code.google.com/p/tspl/downloads/list
偏微分方程求解工具箱 DUNE(目前还不支持windows系统)
DUNE (Distributed and Unified Numerics Environment),分布和统一数值解环境,是一种求解偏微分方程的基于网格的方法(PDE)的模块化的工具箱。DUNE是所有这些体现了科学计算 的概念从抽象的接口设置第一次。现代C + +编程技术使同样的概念非常不同的实现使用一个非常低的开销一个共同的接口。因此,DUNE确保在科学计算的效率,并支持高性能计算应用。
下载地址http://www.dune-project.org/download.html
人工智能应用框架 Into
Into 是一个用 C++ 开发的跨平台的机器智能应用框架。Into 提供一种不同于其他的、快速的方法用以构建高性能图像分析、机器视觉效果、模式识别和人工智能应用。分层的 API 一起超过 20 个完全可互操作的插入式模块用来访问图像和各种数据源等。
下载地址http://intopii.com/into/
高性能计算软件工具包 DAKOTA
DAKOTA (Design Analysis Kit for Optimization and Terascale Applications) 是一种用于执行系统的分析和高性能计算机的设计通用软件工具包。它提供了设计优化,不确定性量化,参数估计,实验设计,灵敏度分析,以及连接服务的计算和 模拟的并行算法范围。
下载地址http://www.cs.sandia.gov/DAKOTA/download.html
线性算术的C++模板库 Eigen
Eigen 是一个线性算术的C++模板库,包括:vectors, matrices, 以及相关算法。功能强大、快速、优雅以及支持多平台。
下载地址  http://bitbucket.org/eigen/eigen/downloads/
多精度整数和有理数 MPIR
MPIR 是一个开源的多精度的整数和有理数计算库,基于 GMP 库开发。
下载地址http://www.mpir.org/mpir-1.3.1.tar.gz
C/C++数值计算库 mygsl
mygsl是一个基于GSL库的个性化开源数值计算项目.
该类库提供了关于数学计算的很多方面,包括:Complex Numbers    Roots of Polynomials
Special Functions    Vectors and Matrices
Permutations    Sorting
BLAS Support    Linear Algebra
Eigensystems    Fast Fourier Transforms
Quadrature    Random Numbers
Quasi-Random Sequences    Random Distributions
Statistics    Histograms
N-Tuples    Monte Carlo Integration
Simulated Annealing    Differential Equations
Interpolation    Numerical Differentiation
Chebyshev Approximation    Series Acceleration
Discrete Hankel Transforms    Root-Finding
Minimization    Least-Squares Fitting
Physical Constants    IEEE Floating-Point
Discrete Wavelet Transforms    Basis splines
下载地址http://u.115.com/file/f572d894a0
     差不多我所知道的就这些了,其实本文主要参考的是开源中国社区公布的一些项目,我所做的仅仅是整理一下呈现给大家,希望对大家在以后的学习、工作有所帮 助。在内心深处里,我其实很想某一天用着比较牛逼的这方面的国产软件,只是不知道会在什么时候。不想带着一种用盗版xp 、office,盗版ug,盗版ansys,盗版GT,盗版AMESim,盗版matlab。。。原来我电脑里装的全是盗版,有时候觉得这是一种多么可笑 的事情,可是又没有什么办法。也许,从这一刻开始,我们带着一种新的理念,多少年后这种情况会得到改观。
     话又说多了···
分类: 算法知识

ZSCGI——– 一个简单的C++ CGI封装

ZSCGI——– 一个简单的C++ CGI封装

本文是继上一篇文章之后的一点深入吧~~ 学了一些关于C/C++ CGI的相关知识,为了方便使用,所以做了这个封装,由于我也是刚刚开始玩CGI,所以写的过程中难免会有所疏漏,所以希望看到这篇文章的朋友,有什么好 的建议,都可以在这里留言,我会一一回复大家的,谢谢!
下面是CGI中用到的环境变量的一个定义,目前只加进去了一部分,如果要扩展,可以有EnvName的最后一项INVALID_ENV之前添加新项的枚举 定义,然后再在EnvNameStr的0之前,添加相应的字符串定义即可,这里需要注意的是,枚举值的定义和字符串的定义一定要对应起来:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#ifndef __EVN_DEF_H__
#define __EVN_DEF_H__
 
enum EnvName
{
 HTTP_HOST,
 HTTP_CONNECTION,
 HTTP_USER_AGENT,
 HTTP_REFERER,
 CONTENT_LENGTH,
 HTTP_CACHE_CONTROL,
 HTTP_ORIGIN,
 CONTENT_TYPE,
 HTTP_ACCEPT,
 HTTP_ACCEPT_ENCODING,
 HTTP_ACCEPT_LANGUAGE,
 HTTP_ACCEPT_CHARSET,
 SERVER_SIGNATURE,
 SERVER_SOFTWARE,
 SERVER_NAME,
 SERVER_ADDR,
 SERVER_PORT,
 REMOTE_ADDR,
 DOCUMENT_ROOT,
 SERVER_ADMIN,
 SCRIPT_FILENAME,
 REMOTE_PORT,
 GATEWAY_INTERFACE,
 SERVER_PROTOCOL,
 REQUEST_METHOD,
 QUERY_STRING,
 REQUEST_URI,
 SCRIPT_NAME,
 INVALID_ENV
};
 
static const char * EnvNameStr[] =
{
 "HTTP_HOST",
 "HTTP_CONNECTION",
 "HTTP_USER_AGENT",
 "HTTP_REFERER",
 "CONTENT_LENGTH",
 "HTTP_CACHE_CONTROL",
 "HTTP_ORIGIN",
 "CONTENT_TYPE",
 "HTTP_ACCEPT",
 "HTTP_ACCEPT_ENCODING",
 "HTTP_ACCEPT_LANGUAGE",
 "HTTP_ACCEPT_CHARSET",
 "SERVER_SIGNATURE",
 "SERVER_SOFTWARE",
 "SERVER_NAME",
 "SERVER_ADDR",
 "SERVER_PORT",
 "REMOTE_ADDR",
 "DOCUMENT_ROOT",
 "SERVER_ADMIN",
 "SCRIPT_FILENAME",
 "REMOTE_PORT",
 "GATEWAY_INTERFACE",
 "SERVER_PROTOCOL",
 "REQUEST_METHOD",
 "QUERY_STRING",
 "REQUEST_URI",
 "SCRIPT_NAME",
 0
};
 
#endif __EVN_DEF_H__
下面即是ZSCGI类,它里面封装了一些比较常用的C/C++ CGI中常用的操作,目前该类的功能还是比较基础的,后续我会在学习的过程中不断的扩展该类的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#ifndef __ZS_CGI_H__
#define __ZS_CGI_H__
 
#include "EnvDef.h"
#include <string>
#include <map>
 
/**
 * @brief this is a utility class for c++ CGI
 */
class ZSCGI
{
public:
 /**
  * @brief get the value of specified environment variable
  * @param eEnvName, the enum definition of the environment variable
  * @return  the point to the value
  */
 static char * GetEnv(EnvName eEnvName);
 /**
  * @brief encode a url
  * @param strSrc, the souce url
  * @param strDest, string to store the encoded url
  */
 static void EncodeUrl(const std::string & strSrc, std::string & strDest);
 /**
  * @brief decode a url
  * @param strSrc, the source url
  * @param strDest, string to store the decoded url
  */
 static void DecodeUrl(const std::string & strSrc, std::string & strDest);
 /**
  * @brief extract variable from a url
  * @param pUrl, the url to be extracted
  * @param mapRes, the result key-value pair set
  */
 static void ExtractVar(const char * pUrl, 
    std::map<std ::string, const char *> & mapRes);
 /**
  * @brief write data to the webpages
  * @param pBuffer, the data buffer
  * @param nLen, the length of data
  * @return the num of bytes written
  */
 static int WriteData(const char * pBuffer, int nLen);
 /**
  * @brief read data from the webserver
  * @param pBuffer, the buffer to store the data
  * @param nLen, the length of the buffer
  * @return the num of bytes read
  */
 static int ReadData(char * pBuffer, int nLen);
 /**
  * @brief print the mine header
  * @param pHeader, the header
  */
 static void MineHeader(const char * pHeader);
private:
 /**
  * @brief convert a char to hexidecimal number
  * @param bCh, the char to be converted
  * @param szBuf, the buffer to store the result
  */
 static void CharToHex(unsigned char bCh, char * szBuf);
 /**
  * @brief convert hexdecimal number to char
  * @param hHigh, the high 4 bits
  * @param bLow, the low 4 bits
  * @return the converted char
  */
 static unsigned char HexToChar(char bHigh, char bLow);
};
 
#endif //__ZS_CGI_H__
</std></map></string>
关于每个API的用法,上面的代码中,已经有比较详细的说明了,在这里,我就不做过多的介绍了。关于该类的实现,我在这里就不贴了,如果有朋友要用该类,那么下面是该类的实现的lib文件:libzscgi.lib,你可以在自己的项目中加入上面的头文件,然后再依赖libzscgi.lib库就可以了,如果有朋友对该类的实现感兴趣的话,可以给我发邮件wuzesheng86@gmail.com
欢迎大家提意见!

事件处理模式之Reactor(二)

事件处理模式之Reactor(二)

        本文是上一篇《事件处理模式之Reactor(一)》的下一篇,上一篇主要介绍了reactor模式的基本理论,这一篇主要通过实例,来介绍Reactor模式的具体使用。在开始本文之前,有必要再说明一下,reactor的源码的地址:reactor源码, 感兴趣的读者朋友可以自己用svn客户端check out到本地。
      如左图所示为reactor项目的基本结构,整体项目分为三个部分:
  • 一是libreactor项目,用来生成reactor相关的lib;
  • 二是server项目,是用reactor实现的一个时间服务器程序;
  • 三是client项目,是用reactor实现的一个客户端程序。
  • 服务端和客户端之间通过telnet协议进行交互,目前仅支持time和exit两个命令,客户向服务端发送time命令,服务端返回当前时间;客 户端向服务端发送exit命令,服务端断开客户端连接。如果要实现其它命令,可以直接通过扩展相关处理逻辑来实现。这里我们关注的重点是reactor模 式,因此不在支持的命令方面做过多的扩展,感兴趣的朋友可以自己进行扩展。
          下面我们来看一下server的实现,从代码中可以看出,server主要包括两个类:
  • 一是TimeServer类,它主要用来处理新的客户端连接请求;
  • 二是RequestHandler类,它主要用来处理客户端与服务端之间的命令交互。
  • 点这里查看服务端源码:reactor_server_test.cc
          接下来,我们来看一下client的实现,从代码中可以看出,client主要包括一个类:
  • TimeClient类,它封装了所有客户端操作,完成与服务端之间的所有交互。
  • 点这里查看客户端源码:reactor_client_test.cc
           通过上面的介绍,以及相关源代码的学习,相信读者朋友对reactor模式的使用有了个初步的印象,下面来总结一下使用reactor的基本步骤,希望能 够对用到的朋友有所帮助。总的来说,要使用reactor模式来实现一个网络server/client包括以下几个步骤:
  • 1. 实现处理读、写、出错事件的EventHandler
  • 2. 把1中实现的EventHandler注册到Reactor中
  • 3. 循环调用Reactor的HandleEvents来促使Reactor进行‘反应’,不断回调EventHandler中的事件处理回调函数。
  • 事件处理模式之Reactor

    事件处理模式之Reactor(一)

    写过大中型网络服务器的朋友相信对事件处理模型(有时也叫事件触发模型)不陌生。今天要讲的Reactor就是在事件处理模型中用的比较多的一种设计模式。请大家先看下面的图,有个初步的印象:

    在上图中,可以看到主要有以下四种角色:
    1. Reactor:
    Reactor是Reactor模式中最为关键的角色,它是该模式最终向用户提供接口的类。用户可以向Reactor中注册 EventHandler(3),然后Reactor在“反应(react)”的时候,发现用户注册的fd上有事件发生,就会回调用户的事件处理函数。下 面是一个简单的设计:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    class Reactor
    {
    public:
     
        /// 构造函数
        Reactor();
     
        /// 析构函数
        ~Reactor();
     
        /// 向reactor中注册关注事件evt的handler(可重入)
        /// @param  handler 要注册的事件处理器
        /// @param  evt     要关注的事件
        /// @retval 0       注册成功
        /// @retval -1      注册出错
        int RegisterHandler(EventHandler * handler, event_t evt);
     
        /// 从reactor中移除handler
        /// @param  handler 要移除的事件处理器
        /// @retval 0       移除成功
        /// @retval -1      移除出错
        int RemoveHandler(EventHandler * handler);
     
        /// 处理事件,回调注册的handler中相应的事件处理函数
        /// @param  timeout 超时时间(毫秒)
        void HandleEvents(int timeout = 0);
     
    private:
     
        ReactorImplementation * m_reactor_impl; ///< reactor的实现类
    };
    2. SynchrousEventDemultiplexer:
    SynchrousEventDemultiplexer也是Reactor中一个比较重要的角色,它是Reactor用来检测用户注册的fd上发生的事 件的利器,通过过Reactor得知了哪些fd上发什么了什么样的事件,然后以些为依据,来多路分发事件,回调用户的事件处理函数。下面是一个简单的设 计:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    class EventDemultiplexer
    {
    public:
     
        /// 获取有事件发生的所有句柄以及所发生的事件
        /// @param  events  获取的事件
        /// @param  timeout 超时时间
        /// @retval 0       没有发生事件的句柄(超时)
        /// @retval 大于0   发生事件的句柄个数
        /// @retval 小于0   发生错误
        virtual int WaitEvents(std::map<handle_t , event_t> * events,
                               int timeout = 0) = 0;
     
        /// 设置句柄handle关注evt事件
        /// @retval 0     设置成功
        /// @retval 小于0 设置出错
        virtual int RequestEvent(handle_t handle, event_t evt) = 0;
     
        /// 撤销句柄handle对事件evt的关注
        /// @retval 0     撤销成功
        /// @retval 小于0 撤销出错
        virtual int UnrequestEvent(handle_t handle, event_t evt) = 0;
    };
    </handle_t>
    3. EventHandler:
    EventHander是用户和Reactor打交道的工具,用户通过向Reactor注册自己的EventHandler,可以告知Reactor在特定事件发生的时候该帮我做些什么。下面是一个简单的设计:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    class EventHandler
    {
    public:
     
        /// 获取该handler所对应的句柄
        virtual handle_t GetHandle() = 0;
     
        /// 处理读事件的回调函数
        virtual void HandleRead() {}
     
        /// 处理写事件的回调函数
        virtual void HandleWrite() {}
     
        /// 处理出错事件的回调函数
        virtual void HandleError() {}
     
    protected:
     
        /// 构造函数,只能子类调
        EventHandler() {}
     
        /// 析构函数,只能子类调
        virtual ~EventHandler() {}
    };
    4. ConcreteEventHandler:
    ConcreteEventHandler是EventHandler的子类,EventHandler是Reactor所用来规定接口的基类,用户自己的事件处理器都必须从EventHandler继承。
    以上简单介绍了一下Reactor模式,最近我自己也在业余时间写了一个可以在windows/linux平台上运行的Reactor库,地址是:http://code.google.com/p/xiao5geproject/source/browse/trunk/reactor/,目前刚刚完成了库的编码,后面抽空我会加上相应的例子,以及单元测试,希望能够对写网络服务器的朋友有所帮助。
    -----------------------------------------------------

    JSON学习小结

    JSON学习小结

    1. 什么是JSON?
    JSON的全称是JavaScript Object Notation, 是一种轻量级的数据交换格式。就像XML一样,JSON也是一种比较常见的数据交换的语言,或者称之为数据交换格式更为贴切。
    2. JSON中的数据结构有下面两种:
    (1)对象(Object): 一系列name/value对的集合
    (2)数组(Array): 一系列有序的values的列表
    3. JSON中基数的数据类型有下面几种:
    (1)对象(Object): 对象是一系列无序的“name/value”集合,如下图所示,对象以’{‘开始,以’}'结束,name和value之间由’:'分隔,多个name/value对之间由’,'分隔。

    (2)数组(Array): 数组是有序的value的列表,如下图所示,数组由’['开始,以']‘结束,多个value之间由’,'分隔。

    (3)值(Value): 值可以是字符串,数字,true,false,null,对象,或者数组,如下图所示。

    (4)字符串(String): 字符串是由双引号括起来的任意的unicode的字符的集合,可以包含由反斜杠开始的转义字符,如下图所示。

    (5)数字(Number): 数字与其它语言中的定义类似,但是这里不支持8进制和16进制,通过用10进制,如下图所示。

    4. JSON使用举例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    {
       "app": {
          "launch": {
             "local_path": "main.html"
          }
       },
       "description": "Chrome App \u4E0A\u7684\u5C0F\u6B66\u54E5\u535A\u5BA2\uFF08\u6D4B\u8BD5\u7248\uFF09.",
       "icons": {
          "128": "128.png",
          "16": "16.png",
          "24": "24.png",
          "48": "48.png"

    [译]c++ web编程:写出你的CGI程序

    [译]c++ web编程:写出你的CGI程序

     一 什么是CGI
          CGI(The Common Gateway Interface):通用网关接口,定义web服务器和客户脚本进行信息交互的一系列标准。
     二 web浏览器
             为了了解CGI的概念,让我们来看看当我们单击一个超链接来浏览一个特定的web页或URL的时候,背后会发生什么事?
          (1)浏览器首先会链接HTTP web 服务器并且请求一个URL 页面;
          (2) WEB服务器将会解析这个URL并且查询请求的文件名,如果找到了请求文件服务器就会将这个文件发送回浏览器,否则发送回一个包含错误信息提示的页面指示你请求的是一个服务器并不包含的文件。
          (3)WEB浏览器将接受来自服务器端的响应,并且向发出请求的用户显示接收到的文件。
            然而,HTTP服务器也可能会以如何这种方式进行配置,那就是无论什么时候接受到对特定目录下的文件的请求,服务器不会将这个文件发送回客户端,而是它作为一个程序被服务器执行,并产生出输出发送回客户端浏览器进行显示。
            CGI(The Common Gateway Interface)是一个标准化的协议,能够使应用程序(通常称为CGI程序或CGI脚本)同web服务器和客户端进行交互。CGI程序能够用 Python, PERL, Shell, C or C++等语言来实现。
    三 CGI程序结构图
           下图简单的展示了CGI程序架构

    四 web服务器配置
            在你着手写CGI程序之前,确保你的web服务器支持CGI程序并且配置成处理CGI程序。所有的能够被HTTP服务器执行的CGI程序都被存放在预先配 置好的目录下面,这个目录叫做CGI目录,并且按照约定命名为 /var/www/cgi-bin,并且约定CGI文件的后缀名为.cgi ,尽管它们是c++可执行文件。
          一般的,Apache 服务器在/var/www/cgi-bin目录下配置文件来运行CGI程序,如果你想要声明另外的目录来运行CGI脚本,你需要修改httpd.conf 文件中的部分内容:
    <Directory "/var/www/cgi-bin">
       AllowOverride None
       Options ExecCGI
       Order allow,deny
       Allow from all
    </Directory>
     
    <Directory "/var/www/cgi-bin">
    Options All
    </Directory>
    

    五 第一个CGI脚本
    以下是一段简短的CGI脚步代码
    #include <iostream>
    using namespace std;
     
    int main ()
    {
        
       cout << "Content-type:text/html\r\n\r\n";
       cout << "<html>\n";
       cout << "<head>\n";
       cout << "<title>Hello World - First CGI Program</title>\n";
       cout << "</head>\n";
       cout << "<body>\n";
       cout << "<h2>Hello World! This is my first CGI program</h2>\n";
       cout << "</body>\n";
       cout << "</html>\n";
       
       return 0;
    }
    
            编译上述代码并且将二进制可执行文件命名为cplusplus.cgi,保存路径为/var/www/cgi-bin目录下,运行chmod 755 cplusplus.cgi 命令使得该文件为可执行的。现在,如果你点击cplusplus.cgi然后就会产生如下输出:
    Hello World! This is my first CGI program
            上面的C++程序是一个将输出写入标准输出文件(stdout)的简单程序。这段代码中有一个很重要的一点那就是第一行代码:Content- type:text/html\r\n\r\n,这行被发送回浏览器,指明浏览器显示的文本类型。现在你应该了解了CGI的基本概念了,你也可以使用 python写出更多复杂的CGI程序,C++ CGI程序能与其他任何外部系统进行信息交互,例如像RDBMS。
    六 HTTP报文头部
           这行字符串” Content-type:text/html\r\n\r\n”是发送回浏览器的HTTP报文头部的一部分,所有的HTTP报文头部都有如下格式:
    HTTP Field Name: Field Content
     
    For Example
    Content-type: text/html\r\n\r\n
    

    下表中包含其他一些重要的HTTP报文信息,这些信息在CGI编程中经常会用到。
    HeaderDescription
    Content-type: A MIME string defining the format of the file being returned. Example is Content-type:text/html
    Expires: Date The date the information becomes invalid. This should be used by the browser to decide when a page needs to be refreshed. A valid date string should be in the format 01 Jan 1998 12:00:00 GMT.
    Location: URL The URL that should be returned instead of the URL requested. You can use this filed to redirect a request to any file.
    Last-modified: Date The date of last modification of the resource.
    Content-length: N The length, in bytes, of the data being returned. The browser uses this value to report the estimated download time for a file.
    Set-Cookie: String Set the cookie passed through the string
    七 CGI环境变量
    所有的CGI程序将会使用到下列的CGI环境变量,这些变量在CGI程序中起着重要的作用。
    Variable NameDescription
    CONTENT_TYPE The data type of the content. Used when the client is sending attached content to the server. For example file upload etc.
    CONTENT_LENGTH The length of the query information. It's available only for POST requests
    HTTP_COOKIE Return the set cookies in the form of key & value pair.
    HTTP_USER_AGENT The User-Agent request-header field contains information about the user agent originating the request. Its name of the web browser.
    PATH_INFO The path for the CGI script.
    QUERY_STRING The URL-encoded information that is sent with GET method request.
    REMOTE_ADDR The IP address of the remote host making the request. This can be useful for logging or for authentication purpose.
    REMOTE_HOST The fully qualified name of the host making the request. If this information is not available then REMOTE_ADDR can be used to get IR address.
    REQUEST_METHOD The method used to make the request. The most common methods are GET and POST.
    SCRIPT_FILENAME The full path to the CGI script.
    SCRIPT_NAME The name of the CGI script.
    SERVER_NAME The server's hostname or IP Address
    SERVER_SOFTWARE The name and version of the software the server is running.
    下面这段代码列出了所有的CGI变量,点击Get Environment可看结果。
    #include <iostream>
    using namespace std;
    
    const string ENV[ 24 ] = {                 
            "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",   
            "HTTP_ACCEPT", "HTTP_ACCEPT_ENCODING",             
            "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION",         
            "HTTP_HOST", "HTTP_USER_AGENT", "PATH",            
            "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT",      
            "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME",
            "SCRIPT_NAME", "SERVER_ADDR", "SERVER_ADMIN",      
            "SERVER_NAME","SERVER_PORT","SERVER_PROTOCOL",     
            "SERVER_SIGNATURE","SERVER_SOFTWARE" };   
    
    int main ()
    {
        
       cout << "Content-type:text/html\r\n\r\n";
       cout << "<html>\n";
       cout << "<head>\n";
       cout << "<title>CGI Envrionment Variables</title>\n";
       cout << "</head>\n";
       cout << "<body>\n";
       cout << "<table border = \"0\" cellspacing = \"2\">";
    
       for ( int i = 0; i < 24; i++ )
       {
           cout << "<tr><td>" << ENV[ i ] << "</td><td>";
           // attempt to retrieve value of environment variable
           char *value = getenv( ENV[ i ].c_str() );  
           if ( value != 0 ){
             cout << value;                                 
           }else{
             cout << "Environment variable does not exist.";
           }
           cout << "</td></tr>\n";
       }
       cout << "</table><\n";
       cout << "</body>\n";
       cout << "</html>\n";
       
       return 0;
    }
     
    
    八 C++CGI库
    在该FTP服务器上ftp://ftp.gnu.org/gnu/cgicc/ 提供了C++ CGI库以供下载,我们从上面下载CGI 库并一下步骤进行安装:
          $tar xzf cgicc-X.X.X.tar.gz 
    $cd cgicc-X.X.X/
    $./configure --prefix=/usr
    $make
    $make install
    并且你可以阅读相关文档。C++ CGI Lib Documentation
    九 GET 与POST方法
            当你需要从浏览器客户端传递信息至web服务器端并最终送至CGI程序的时候,你将必然会遇到很多的问题。大部分的浏览器使用两种方法发送信息至浏览器:GET方法和POST方法,进行过WEB开发的人应该对其很熟悉。
            1. 使用GET方法发送信息
           GET方法将编码过的用户信息附加在页面请求上发送,页面请求和这些编码信息使用?进行分割,如下所示:
           http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2
            GET方法是浏览器发送信息之服务器端所采用的默认的方法,采用这种方法发送时,在你的浏览器地址栏上在URL后面会附加上一串字符串,如果你传输密码或 其他敏感信息至服务器端的时候不要使用GET方法,GET方法有长度限制,在一个请求字符串中,最多只能发送1024的字符。
    当使用GET方法的时候,HTTP报文头采用QUERY_STRING发送信息,并且将通过QUERY_STRING环境变量进入你的CGI程序。
    您能够使用简单的键-值组合附加在URL后传递信息,或者你也可使用HTML中的<FORM>标签通过使用GET方法来传递信息。
             2. 使用POST方法发送信息
            CGI程序中较为通用的且更为可靠地传递信息的方法是POST方法,POST传递的报文信息和GET方法没什么两样,但是跟GET方法的将字符串信息附加 于URL之后并且用?分隔有所区别的是,POST方法使用分离的报文段分别发送URL和要传输的信息。这些信息会被CGI脚本以标准输入的形式接收。
    (注:在原文中作者给出了HTML各种控件传递信息给CGI脚本的例子,有兴趣的朋友可以去看看)
    十 在CGI中使用Cookies
            服务器可能会以Cookies的形式发送数据给客户端浏览器上,浏览器也许会接收这些Cookies,并且会以简单文本的形式存储在用户的硬盘上,当用户 访问该web站点的另外页面的时候,这些Cookies就会有用处了,服务器就会据此知道用户记录了那些信息。
            Cookies信息格式包含如下5个变量:
         (1) Expires:包含Cookies的过期信息。如果变量值为空,当客户端关闭浏览器时,Cookies就会过期。
        (2)  Domain:web站点的域名信息。
        (3)  Path:设置Cookies的web页或目录的路径。如果想要从任何页面或目录获取Cookies信息,此变量设为空值。
        (4)  Secure:如果该字段设置为"secure",那么Cookies将只能被安全服务器获取,如果该字段为空,则没有该限制。
        (5)  Name=Value:Cookies以键-值对的形式设置或获取。
          1. 设置Cookies
           发送Cookies信息至浏览器是非常容易的,这些Cookies将会附加在在HTTP报文头的Content-type域前。假设你想要以Cookies的方式设置UserID和Password,那么简单的CGI设置脚本如下:
         
    #include <iostream>
    using namespace std;
    
    int main ()
    {
     
       cout << "Set-Cookie:UserID=XYZ;\r\n";
       cout << "Set-Cookie:Password=XYZ123;\r\n";
       cout << "Set-Cookie:Domain=www.tutorialspoint.com;\r\n";
       cout << "Set-Cookie:Path=/perl;\n";
       cout << "Content-type:text/html\r\n\r\n";
    
       cout << "<html>\n";
       cout << "<head>\n";
       cout << "<title>Cookies in CGI</title>\n";
       cout << "</head>\n";
       cout << "<body>\n";
    
       cout << "Setting cookies" << endl;  
      
       cout << "<br/>\n";
       cout << "</body>\n";
       cout << "</html>\n";
       
       return 0;
    }
    

            从这个例子中你将了解怎么设置Cookies,那就是使用Set-Cookie来设置Cookies。
            设置Cookies属性的时候,Expires, Domain, and Path是可选的,值得注意的一点是Cookies的设置是在发送"Content-type:text/html\r\n\r\n”之前。运行/cgi-bin/setcookies.cgi将会在你的电脑上设置Cookies。
    2.获取Cookies
          获取Cookies也非常简单,Cookies都存储在CGI的环境变量HTTP_COOKIE中,并且具有如下的格式:
          key1=value1;key2=value2;key3=value3....
         以下就是一段获取Cookies的简短的CGI代码:
    #include <iostream>
    #include <vector>  
    #include <string>  
    #include <stdio.h>  
    #include <stdlib.h> 
     
    #include <cgicc/CgiDefs.h> 
    #include <cgicc/Cgicc.h> 
    #include <cgicc/HTTPHTMLHeader.h> 
    #include <cgicc/HTMLClasses.h>
    
    using namespace std;
    using namespace cgicc;
    
    int main ()
    {
       Cgicc cgi;
       const_cookie_iterator cci;
    
       cout << "Content-type:text/html\r\n\r\n";
       cout << "<html>\n";
       cout << "<head>\n";
       cout << "<title>Cookies in CGI</title>\n";
       cout << "</head>\n";
       cout << "<body>\n";
       cout << "<table border = \"0\" cellspacing = \"2\">";
       
       // get environment variables
       const CgiEnvironment& env = cgi.getEnvironment();
    
       for( cci = env.getCookieList().begin();
            cci != env.getCookieList().end(); 
            ++cci )
       {
          cout << "<tr><td>" << cci->getName() << "</td><td>";
          cout << cci->getValue();                                 
          cout << "</td></tr>\n";
       }
       cout << "</table><\n";
      
       cout << "<br/>\n";
       cout << "</body>\n";
       cout << "</html>\n";
       
       return 0;
    }
    
    点击/cgi-bin/getcookies.cgi看看效果,将会显示出之前设置过的Cookies。
     译自:http://www.tutorialspoint.com/cplusplus/cpp_web_programming.htm (部分略去未译)。


    作者:lgp88 发表于2012-2-22 10:50:22 原文链接
    阅读:441 评论:1 查看评论

    在Windows下使用Python创建cgi程序

    在Windows下使用Python创建cgi程序  

    2012-12-12 09:20:56|  分类: python |字号 订阅
    软件环境:
    Windows/Python 3.x/Apache
    如果是python2.X的话,可以使用modpython进行python的web编程。如果升级到python3.X的话,则可以使用wsgi。因为modpython不支持python3
    在这里介绍使用cgi进行python的web编程,然后通过简单的例子进行示范。
    使用php编程的童鞋都知道,apache在运行php程序之前需要对apache进行配置。同样,使用python也需要配置。
    python的apache配置基本上四个步骤:
    1、打开http.conf,找到 #ScriptInterpreterSource Registry,把前面的#去掉。如果没有找到这句话,则自行添加。
    2、找到AddHandler cgi-script,去掉前面的#,在后面加上.py
    3、找到Options Indexes FollowSymLinks,在其后加上ExecCGI, 去掉 Indexes
    4、保存,重启apache。
    之后就可以进行python的编程了,编辑 p.py:
    1. #!D:\\software\python\python.exe   
    2. #encoding:gb2312   
    3. #import cgi, cgitb    
    4. print("Content-type:text/html\r\n\r\n")  
    5. print("<html>")  
    6. print("<head><title>Hello,python</title></head>")  
    7. a="100";  
    8. print("<body><h1>hello, i am " )  
    9. print(a)  
    10. print("</h1></body>")  
    11. print("</html>")  
    然后在浏览器中输入: 127.0.0.1/p.py,就可以看到输出了:

    powerShell中调用Win32API

    PowerShell中调用Win32API 2008-06-03 22:01:47
    分类: WINDOWS
    调用Win32 API, 取得网络文件夹的剩余空间. 用户无需挂载磁盘即可取得结果
    $a = Add-Type -memberDefinition @"
    [DllImport("Kernel32.dll")]
    public static extern bool GetDiskFreeSpaceEx(
    string lpDirectoryName,
    out long lpFreeBytesAvailable,
    out long lpTotalNumberOfBytes,
    out long lpTotalNumberOfFreeBytes
    );
    "@ -passthru -name MyGetDiskFreeSpaceEx
    $fba = [int64] 0;
    $tnb = [int64] 0;
    $nfb = [int64] 0;
    $a::GetDiskFreeSpaceEx("\\.host\Shared Folders\files", [ref] $fba, [ref] $tnb, [ref] $nfb)
    "FreeBytesAvailable: $($x)"
    "TotalNumberOfBytes: $($y)"
    "TotalNumberOfFreeBytes: $($z)"
    ------------OLD------------
    $a = Add-Type -memberDefinition @"
    [DllImport("Kernel32.dll")]
    public static extern bool GetDiskFreeSpaceEx(
    string lpDirectoryName,
    IntPtr lpFreeBytesAvailable,
    IntPtr lpTotalNumberOfBytes,
    IntPtr lpTotalNumberOfFreeBytes
    );
    "@ -passthru -name MyGetDiskFreeSpaceEx
    $fba = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(20);
    $tnb = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(20);
    $nfb = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(20);

    $a::GetDiskFreeSpaceEx("\\.host\Shared Folders\files", $fba, $tnb,  $nfb)

    $x = [System.Runtime.InteropServices.Marshal]::ReadInt64($fba)
    $y = [System.Runtime.InteropServices.Marshal]::ReadInt64($tnb)
    $z = [System.Runtime.InteropServices.Marshal]::ReadInt64($nfb)
    "FreeBytesAvailable: $($x)"
    "TotalNumberOfBytes: $($y)"
    "TotalNumberOfFreeBytes: $($z)"
    [System.Runtime.InteropServices.Marshal]::FreeHGlobal($fba);
    [System.Runtime.InteropServices.Marshal]::FreeHGlobal($tnb);
    [System.Runtime.InteropServices.Marshal]::FreeHGlobal($nfb);

    使用WMI对象的方法

    【探索PowerShell 】【十四】使用WMI对象的方法 2010-04-18 10:21:54
    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://marui.blog.51cto.com/1034148/298520
    上一篇文章中介绍了WMI的基础内容,主要讲了WMI的属性值的查看,文中还提到,WMI不仅具有属性,还具有方法。这一节就来具体讲一下如何调用WMI对象方法。
    通过查看WMI对象,可以发现有不少的类同时具有属性和方法。例如类"Win32_NetworkAdapterConfiguration",j就具有不少的方法和属性,可以使用以下命令查询:
    Get-WmiObject Win32_NetworkAdapterConfiguration | Get-Member -MemberType Methods | Format-List 
    列出的可用的方法有:
    • DisableIPSec
    • EnableDHCP
    • EnableIPSec
    • EnableStatic
    • ReleaseDHCPLease
    • RenewDHCPLease
    • SetDNSDomain
    • SetDNSServerSearchOrder
    • SetDynamicDNSRegistration
    • SetGateways
    • SetIPConnectionMetric
    • SetIPXFrameTypeNetworkPairs
    • SetTcpipNetbios
    • SetWINSServer
    • ConvertFromDateTime
    • ConvertToDateTime
    • Delete
    • GetType
    • Put
    同样,使用如下命令查询其属性成员:
    Get-WmiObject Win32_NetworkAdapterConfiguration | Get-Member -MemberType Property | Format-List 
    通过以上命令查询,类"Win32_NetworkAdapterConfiguration"有着方法"EnableDHCP"和属性"IPEnabled"。下面,就用此这两个成员来说明如何调用类的方法。
    在这个类中,方法"EnableDHCP"的作用是开启、关闭网络适配器DHCP功能,属性"IPEnable"则是一个bool值,反应是否有 IP配置,有则为"true"反之则为"false"。用"IPEnable"可以过滤我们可以跳过任何断开的、虚拟的网络适配设备。
    例如我们可以使用如下命令来改变DHCP设置:
    1. $Network=get-wmiobject win32_NetworkAdapterConfiguration | where{  
    2. $_.IPEnabled -eq "true"}  
    3. foreach($NIC in $Network){  
    4. $NIC.EnableDHCP()} 
    这段脚本首先会判断"IPEnable"是否为真,如果是,则开启DHCP,否则不进行操作。
    类"Win32_NetworkAdapterConfiguration"还具有另外的方法,如"$NIC.SetDNSServerSearchOrder()",可以使用这个方法改变DNS设置,改变是否“自动获取DNS”的设置。
    1. $Network=get-wmiobject win32_NetworkAdapterConfiguration | where{$_.IPEnabled -eq "true"}  
    2. foreach($NIC in $Network){  
    3. $NIC.EnableDHCP()  
    4. $NIC.SetDNSServerSearchOrder()  
    需要注意的是,在调用不同的方法时,需要不同类型的数据参数,这一点需要非常留心。在前文查询方法的命令输出中,在"Definition"字段便可以看到具体数据格式要求:

    【探索PowerShell 】【十三】WMI对象

    【探索PowerShell 】【十三】WMI对象 2010-04-16 08:53:55
    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://marui.blog.51cto.com/1034148/296083
    我记得在xp时代,经常使用的工具有一个叫做WMI Administrative Tools,是微软官方提供的用来查看、编辑WMI对象的,只是现在好似不支持新的系统了。但是,在Win7、Server 2008下,这些功能都可以方便的通过PowerShell来完成。
    首先,先来认识一下什么是WMI对象:
    WMI是作为一个基本的数据库存在于Windows系统中的。我们可以连接到WMI服务请求查询其中所包含的信息。WMI包括了系统方方面面的信息,包括:
      •  机器信息:制造商、型号、序列号等
      •  BIOS信息
      •  OS信息
      •  CPU信息:种类、制造商、速度、版本
      •  服务器内存总量
      •  磁盘信息:容量、格式等
      •  网络信息:MAC、IP等
      •  其他
    可以看出WMI内容是多么的丰富,几乎包括了计算机的方方面面。
    利用PowerShell查看WMI成员
    在PowerShell中通过以下命令列出WMI对象:
    get-wmiObject -list -namespace “root\CIMV2″ <enter> 

    需要具体查看某个类的成员,使用下面的命令(例如类"win32_process"):
    get-wmiobject -class win32_process -namespace "root\cimv2" | get-member 

    可以看到每个有的成员是属性(Property),而有的则是方法(Method)。
    那么,有两个问题:
    为什么要使用-namespace "root\cimv2" 
    cimv2是WMI的一个命名空间,每个命名空间下有不同的WMI对象成员。cimv2是其默认设置。可以按照以下步骤进行修改:
    控制面板 -> 管理工具 -> 计算机管理 -> 服务和应用程序 -> 右键"WMI控制" -> 属性 -> 高级
    参数"-namespace"并非必须,但是,使用它有两个好处,一是保证我们能准确的查看指定命名空间下的WMI对象,因为有时默认命名空间并非我们所希望查看的;二是如果不指定命名空间,被设置过的计算机可能拒绝我们的访问请求。
    注:因为我使用英文版系统,上述步骤中个别名称可能不准确。

    在如上图所示的界面,即可修改默认路径。
    另一个问题是,查看成员的类型有什么用?
    如果一个成员是方法,那么,我们可以调用它。如果一个成员是属性,我们则可以查看它的值。但是,需要注意的是,不同的属性成员有不同的数据结构,有 的是"System.String",有的是"System.UInt32",有的则是"System.String[ ]",在使用时,应当注意数据格式,否则会报错的。
    如果我们需要管理网络中的计算机,则需要指定计算机名称:
    get-wmiObject -list -namespace “root\CIMV2″ -computername 计算机名 <enter> 
    好了,现在来具体操作,查看具体信息。
    例:
    查看BIOS信息
    get-wmiobject -class win32_bios -namespace "root\cimv2" <enter> 
    运行结果:

    查看服务信息
    get-wmiobject -class win32_service -namespace "root\cimv2" | format-list * <enter> 
    查看机器信息
    get-wmiobject -class win32_computersystem | format-list * <enter> 

    在网络管理环境中的多数情况下,我们可能要查看不同的计算机信息,因此,就需要使用计算机这一参数,例如:
    查询本地计算机的网络信息
    1. $name="." 
    2.  
    3. $items = get-wmiObject -class win32_NetworkAdapterConfiguration '
    4. -namespace "root\CIMV2" -ComputerName $name | where{$_.IPEnabled -eq “True”}  
    5.  
    6. foreach($obj in $items) {  
    7. Write-Host "DHCP Enabled:" $obj.DHCPEnabled  
    8. Write-Host "IP Address:" $obj.IPAddress  
    9. Write-Host "Subnet Mask:" $obj.IPSubnet  
    10. Write-Host "Gateway:" $obj.DefaultIPGateway  
    11. Write-Host "MAC Address:" $ojb.MACAddress  
    如果查询对象是其他机器,只需给变量"$name"赋与其他值即可。
    例如:
    1. $name=read-host "Enter Computer Name"
    2. write-host "Computer:"$name 
    3.  
    4. $items = get-wmiObject -class win32_NetworkAdapterConfiguration '
    5. -namespace "root\CIMV2" -ComputerName $name | where{$_.IPEnabled -eq “True”}  
    6.  
    7. foreach($obj in $items) {  
    8. Write-Host "DHCP Enabled:" $obj.DHCPEnabled  
    9. Write-Host "IP Address:" $obj.IPAddress  
    10. Write-Host "Subnet Mask:" $obj.IPSubnet  
    11. Write-Host "Gateway:" $obj.DefaultIPGateway  
    12. Write-Host "MAC Address:" $ojb.MACAddress  
    配合更多的查询命令,便可以方便的写出一个查询计算机信息的脚本,在本教程的结束部分,我会尽可能多的提供各种常用脚本。本节内容就先写到这里。
    本文出自 “马睿的技术博客” 博客,请务必保留此出处http://marui.blog.51cto.com/1034148/296083

    app engine java api 重点

    https://developers.google.com/appengine/docs/java/images/?hl=zh-CN


    https://developers.google.com/appengine/docs/java/images/?hl=zh-CN

    怎样用本地的Java代码和服务端的Servlet进行通信

    怎样用本地的Java代码和服务端的Servlet进行通信

    分类: Android 402人阅读 评论(0) 收藏 举报
    一,编写servlet类:

    ReverseServlet类实现了将,客户端上传的String反转,并返回给客户端的功能。

    1. public class ReverseServlet extends HttpServlet  
    2. {  
    3.     private static String message = "Error during Servlet processing";  
    4.       
    5.     public void doPost(HttpServletRequest req, HttpServletResponse resp) {  
    6.         try {  
    7.             int len = req.getContentLength();  
    8.             byte[] input = new byte[len];  
    9.           
    10.             ServletInputStream sin = req.getInputStream();  
    11.             int c, count = 0 ;  
    12.             while ((c = sin.read(input, count, input.length-count)) != -1) {  
    13.                 count +=c;  
    14.             }  
    15.             sin.close();  
    16.           
    17.             String inString = new String(input);  
    18.             int index = inString.indexOf("=");  
    19.             if (index == -1) {  
    20.                 resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);  
    21.                 resp.getWriter().print(message);  
    22.                 resp.getWriter().close();  
    23.                 return;  
    24.             }  
    25.             String value = inString.substring(index + 1);  
    26.               
    27.             //decode application/x-www-form-urlencoded string  
    28.             String decodedString = URLDecoder.decode(value, "UTF-8");  
    29.               
    30.             //reverse the String  
    31.             String reverseStr = (new StringBuffer(decodedString)).reverse().toString();  
    32.               
    33.             // set the response code and write the response data  
    34.             resp.setStatus(HttpServletResponse.SC_OK);  
    35.             OutputStreamWriter writer = new OutputStreamWriter(resp.getOutputStream());  
    36.               
    37.             writer.write(reverseStr);  
    38.             writer.flush();  
    39.             writer.close();  
    40.         } catch (IOException e) {  
    41.             try{  
    42.                 resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);  
    43.                 resp.getWriter().print(e.getMessage());  
    44.                 resp.getWriter().close();  
    45.             } catch (IOException ioe) {  
    46.             }  
    47.         }  
    48.           
    49.     }    
    50.           
    51. }  

    二,编写web.xml文件:
    1. <?xml version="1.0" encoding="ISO-8859-1"?>  
    2. <web-app xmlns="http://java.sun.com/xml/ns/j2ee"  
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    4.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"  
    5.     version="2.4">  
    6.       <servlet>  
    7.         <servlet-name>ReverseServlet</servlet-name>  
    8.         <servlet-class>com.servlet.service.test.ReverseServlet</servlet-class>  
    9.      </servlet>  
    10.       
    11.     <servlet-mapping>  
    12.         <servlet-name>ReverseServlet</servlet-name>  
    13.         <url-pattern>/servlet/ReverseServlet</url-pattern>  
    14.     </servlet-mapping>  
    15. </web-app>  

    三,分别部署.class文件和web.xml到WEB-INF/classes和WEB-INF/

    四,编写客户端类:
    1. public class Reverse {  
    2.     public static void main(String[] args) throws Exception {  
    3.   
    4. //  if (args.length != 2) {  
    5. //      System.err.println("Usage:  java Reverse " +  
    6. //                               "http://<location of your servlet/script>" +   
    7. //                               " string_to_reverse");  
    8. //      System.exit(1);  
    9. //  }  
    10.   
    11.     String urlStr = "http://localhost:8080/myservicetest/servlet/ReverseServlet";  
    12.     String strStr = "hello word!";  
    13.     String stringToReverse = URLEncoder.encode(strStr, "UTF-8");  
    14.   
    15.     URL url = new URL(urlStr);  
    16.     URLConnection connection = url.openConnection();  
    17.     connection.setDoOutput(true);  
    18.   
    19.     OutputStreamWriter out = new OutputStreamWriter(  
    20.                               connection.getOutputStream());  
    21.     out.write("string=" + stringToReverse);  
    22.     out.close();  
    23.   
    24.     BufferedReader in = new BufferedReader(  
    25.                 new InputStreamReader(  
    26.                 connection.getInputStream()));  
    27.                   
    28.     String decodedString;  
    29.   
    30.     while ((decodedString = in.readLine()) != null) {  
    31.         System.out.println(decodedString);  
    32.     }  
    33.     in.close();  
    34.     }  
    35. }  

    五,启动webserver 和本地java程序。

    运行结果如下:!drow olleh