实现类似路由器那样通过WEB页面配置设备

实现通过web来与其他进程交互

        要像路由器那样,通过访问一个网页就能配置设备,实质上是web服务器与其他进程的通信问题。关键在于,我们的web服务器收到浏览器的请求时能够通知另外一个进程来处理。通常配置一个设备的程序可以用高级或者低级语言来实现,但是苦于不知道我们何时配置或者配置什么,而只有与用户交互的web页面知道。只要我们的web页面能够告诉我们的配置进程要配置的参数,那么问题就迎刃而解。

        最简单的就是通过数据库来实现,因为web程序都支持数据库,当收到用户请求时,把要配置的参数等都写入数据库,并写入一个标志,而我们的配置进程由定时器触发不断地读取数据库,当发现标志被改了,再读取配置参数进行相应的配置。这是最简单的一种结构。

         另一种就是web程序通过socket套接字与其他进程交互。socket套接字的应用广泛而且跨平台得很,只要你的网页的服务器代码能支持socket基本上就完事了,像PHP、C#等都比较好做。偏偏我只会一点c和c++....尽量找能支持c或c++的做法。果然让我找到fastCGI。官网是www.fastcgi.com。里面都有详细的介绍等。fastCGI说白了其实是实现一个main函数。在这个main函数里,没有请求的时候就阻塞,有请求的时候,函数就接着运行,通常是一个循环不断等待来自浏览器的请求。而对于每个请求,服务器以及客户端的很多信息都可以通过request的环境变量获得,例如该请求是GET还是POST等。而客户发过来的数据(例如POST)就通过标准stdin例如getchar()等得到。至于对于请求怎么响应你完全可以用熟悉的c来做。最后要返回给用户的html代码通过stdout来输出给用户。例如printf()、fprintf()等。

        很多网络服务器都支持fastCGI,我使用的是在linux平台的apache服务器,一切用到的都支持跨平台。当然apache服务器太强大了,如果像路由器这样的嵌入式设备还是采取轻量级的服务器好些。apache服务器接收来自客户浏览器browser的请求,再把请求转由fastCGI进程来处理。fastCGI程序支持多种语言如perl,php,java,c,c++等,既然可以用C语言来实现,那就是说可以在fastCGI函数里面使用 socket等等等等为所欲为,通过socket,fastCGI就能于其他进程或者其他机器上的进程通信。


inux下配置apache服务器、fastCGI模块以及 fastCGI development kit

         配置apache服务器的fastCGI模块花了我好几天的时间,一直在尝试把fast-dev-kit里面的例子跑起来,主要是配置问题。解压httpd-2.2.19.tar.gz(apache_http服务器)、mod_fcgid- 2.3.6(apache_http服务器的fastcgi模块)、fcgi-2.4.0(fastCGI c或c++的开发包),里面有readMe文件也有介绍。先在httpd-2.2.19下./configure默认配置.再make,make install安装好apache服务器。安装完后会在/usr/local/下出现apache2目录,在usr/local/apache/bin下启动apache服务器,./apachectl -k start。在浏览器输入localhost看apache服务器是否成功启动。接着安装mod_fcgid-2.3.6,在其目录下有个 configure.apxs文件,需要通过apache2/bin/下的apxs程序来配置,运行APX=/usr/local/apache2 /bin/apxs ./configure.apxs来配置fastCGI模块,接着make,makeinstall安装。安装完后会在apache/modules/下多了mod_fcgid.so文件,说明fastCGI模块已安装成功。fastCGI开发包同样也是./configure、make、make install安装。


用C语言实现一个fastCGI程序:

程序如下:
#include "fcgi_stdio.h"
#include <stdlib.h>

   int main()
   {
       int count = 0;
       while(FCGI_Accept() >= 0)
           printf("Content-type: text/html\r\n"
                  "\r\n"
                  "<title>FastCGI Hello!</title>"
                  "<h1>FastCGI Hello!</h1>"
                  "Request number %d running on host <i>%s</i>\n",
                   ++count, getenv("SERVER_NAME"));

    return 0;
   }

        当用户有请求时,FCGI_Accept()就会返回。这里的printf是fcgi_stdio.h里的printf,printf的内容会返回给用户。程序的编译需要开发包下的/libfcgi/下的fcgi_stdio.c、 fcaiapp.c、和os_unix.c。用g++来编译。还要把开发包下的include文件加入路径。编译可能会报错因为socklen_t的问题。看了os_unix.c的源代码之后你就明白了,我为求方便加了个宏定义就编译通过了。生成程序tiny.fcg。
        接下来得配置apache服务器,使它可以运行我们的tiny.fcg程序。apache的服务器的配置都在/conf/下的httpd.conf文件里。
在里面添加如下信息:

LoadModule fcgid_module modules/mod_fcgid.so

<Directory "/usr/local/apache2/fcgi-bin">
    SetHandler fcgid-script
    AllowOverride None
    Options None
    Order allow,deny
    Allow from all
</Directory>


          大家注意了,我之所以花了几天时间fastCGI程序都跑不起来就是因为SetHandler项,我一直写了fcgi-script!!!少了一个d。我还重装了两遍apache..最后终于让我发现了。一改为fcgid-script。。终于可以了!当访问出错的时候,apache会把错误记录在apache/logs/下的error_log和access_log,当你调试fastCGI程序的时候,这两个文件给你很大帮助。

          apache的配置文件里的语法官网都有介绍,要是你配置了还跑不起来,你就得像我那样去啃官网的英文文档了看天意了。。。。
          配置好后fcgi-bin文件夹里面的程序收到请求时都自动调用fastCGI来跑。假设我们里面有tiny.fcg文件。那么访问localhost/fcgi-bin/tiny.fcg时,请求就交由tiny.fcg处理了。正如我们c语言实现那样网页返回以下内容:
FastCGI Hello!
Request number 1 running on host localhost
刷新几次之后,number会变化。

        整个过程,我们充当一个web服务器的角色,对于用户的请求,由我们来生成html页面,然后把html源码通过printf或其他stdout返回给用户。还得熟悉下html以及javascript脚本语言这程序才好写啊。



fastCGI如何获得用户GET或者POST过来的数据

有代码有真相:先贴再解释


#include "fcgi_config.h"
#include "fcgiapp.h"
#include <sys/types.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif


int main(void)
{

    int rc;

    FCGX_Init();
    pid_t pid = getpid();
    FCGX_Request request;
    char *server_name;

    FCGX_InitRequest(&request, 0, 0);

    for (;;)
    {
        rc = FCGX_Accept_r(&request);

        if (rc < 0)
            continue;

        char buffer[1024*10];
        buffer[0] = '\0';
        char** p = request.envp;
        while(*p)
        {
            strcat(buffer,*p);
            strcat(buffer,"\r\n");
            p++;
        }

        server_name = FCGX_GetParam("SERVER_NAME", request.envp);

        FCGX_FPrintF(request.out,
            "Content-type: text/html\r\n"
            "\r\n"
            "<title>FastCGI Hello!</title>"
            "<h1>FastCGI Hello! </h1>"
             "<p>Process %ld</p>"
            "<p> host<i>%s</i></p>"
            "the environments we get is: <p>"
            "<pre>%s</pre>",
            pid, server_name ? server_name : "?",buffer);


        //
        char* method = FCGX_GetParam("REQUEST_METHOD",request.envp);
        if(strcmp(method,"POST") == 0)
        {
            char postedData[1024*10];
            int dataNum = 0;
            int ch;
            while((ch = FCGX_GetChar(request.in)) != -1)
            {
                postedData[dataNum++] = (char)ch;
            }

            postedData[dataNum] = '\0';

            FCGX_FPrintF(request.out,
                         "<p>the data posted is:</p>"
                         "<pre>%s</pre>",postedData);
        }

        FCGX_Finish_r(&request);

    }
        return 0;
}


      基本上你看到函数名字大概就能猜到了,并且可以看源代码的。首先看以下 FCGX_Request的结构。


typedef struct FCGX_Request {
    int requestId;            /* valid if isBeginProcessed */
    int role;
    FCGX_Stream *in;
    FCGX_Stream *out;
    FCGX_Stream *err;
    char **envp;

    /* Don't use anything below here */

    struct Params *paramsPtr;
    int ipcFd;               /* < 0 means no connection */
    int isBeginProcessed;     /* FCGI_BEGIN_REQUEST seen */
    int keepConnection;       /* don't close ipcFd at end of request */
    int appStatus;
    int nWriters;             /* number of open writers (0..2) */
    int flags;
    int listen_sock;
} FCGX_Request;


       里面的in就是stdin,可以读取由浏览器POST过来的数据。out就是输出,往out printf的内容将返回给浏览器用户。envp就是字符串数组的指针,里面保存的都是环境变量,源代码就把这些环境变量都打印出来了。把fastCGI程序(我起名为learnFCGI)放入apache服务器的fcgi-bin文件夹(已配置好)。我在浏览器访问localhost/fcgi-bin/learnCGI得到以下内容


FastCGI Hello!

Process 12660

hostlocalhost

the environments we get is:FCGI_ROLE=RESPONDER

HTTP_HOST=localhost

HTTP_USER_AGENT=Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100626 SUSE/3.6.6-1.2 Firefox/3.6.6

HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

HTTP_ACCEPT_LANGUAGE=en-us,en;q=0.5

HTTP_ACCEPT_ENCODING=gzip,deflate

HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.7

HTTP_CONNECTION=close

PATH=/usr/lib64/mpi/gcc/openmpi/bin:/sbin:/usr/sbin:/usr/local/sbin:/root/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib/mit/bin:/usr/lib/mit/sbin

SERVER_SIGNATURE=

SERVER_SOFTWARE=Apache/2.2.19 (Unix) mod_fcgid/2.3.6

SERVER_NAME=localhost

SERVER_ADDR=::1

SERVER_PORT=80

REMOTE_ADDR=::1

DOCUMENT_ROOT=/usr/local/apache2/htdocs

SERVER_ADMIN=you@example.com

SCRIPT_FILENAME=/usr/local/apache2/fcgi-bin/learnFCGI

REMOTE_PORT=45762

GATEWAY_INTERFACE=CGI/1.1

SERVER_PROTOCOL=HTTP/1.1

REQUEST_METHOD=GET

QUERY_STRING=

REQUEST_URI=/fcgi-bin/learnFCGI

SCRIPT_NAME=/fcgi-bin/learnFCGI

       由于我是直接访问的,所以即使REQUEST_METHOD为GET,QUERY_STRING也为空,另外也没有POST的数据,不妨写个简单的HTML页面测试下。

代码如下:

<html>
<body>
<form action="/fcgi-bin/learnFCGI" method="get">
    name:<input type="text" name="myName" ></br>
    passwrod:<input type="text" name="myPassword"></br>
    <input type="submit" value="提交">
</form>
</body>
</html>


         把html保存为testpage.html放在apache的usr/local/apache2/htdocs目录下。就能访问了,我这里通过localhost/testpage.html得到


         往文本框里输入testname,testpassword.按提交则会转到learnFCGI程序。我们会发现,这次打印的环境变量的QUERY_STRING发生了变化:


QUERY_STRING=myName=testname&myPassword=testpassword

我们的内容提交到fastCGI程序了。


把html代码里<form> 中的method属性改为 method="post",再次运行就能看到POST数据了


REQUEST_METHOD=POST

QUERY_STRING=

REQUEST_URI=/fcgi-bin/learnFCGI

SCRIPT_NAME=/fcgi-bin/learnFCGI


the data posted is:

myName=testname&myPassword=testpassword

        在使用fastCGI的过程中,网上的资料不是很多。。基本上我就去官网啃英文,啃了好几遍还的不出个怎么写法。只好去试。。最重要的是多写小程序来测试。。好像FCGX_Request里面的环境变量有什么内容本来我也不知道,那就写个程序把里面的都打印出来。。发现原来里面有个REQUEST_METHOD和QUERY_STRING选项,我就知道可以往fastCGI提交数据。并尝试把getchar()验证是否能获得POST的数据。


      这样,通过fastCGI,web程序就能把数据提交给另外一个进程处理了。

  • 8
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值