zoukankan      html  css  js  c++  java
  • Linux下嵌入式Web服务器BOA和CGI编程开发



    **目录**
    一、环境搭建
    二、相关配置(部分)
    三、调试运行
    四、测试源码参考
    五、常见错误
    六、扩展(CCGI,SQLite)



    # 一、环境搭建
    操作系统:Ubuntu12.04 LTS
    boa下载地址(但是我找不到...): http://www.boa.org/
    我是其他网站找到的资源,但是忘了网址了,所以我直接上云盘资源
    链接: https://pan.baidu.com/s/1_SpR9MDcmSB8jpDm76fw6A 提取码: hb1e
    可以参考:Ubuntu下boa服务器的配置与搭建
    cgi:直接终端安装 sudo apt-get install apache2
    可以参考: ubuntu 下搭建cgi环境

    # 二、相关配置(部分)
    boa我的配置:/etc/boa$ sudo vi boa.conf

    # 下面几个都是关键点,基本就错这几个点上
    # cumentRoot /var/www
    #将cgi保存的实际位置和网站地址做个对应
    # ScriptAlias /cgi-bin/ /var/www/cgi-bin/
    #cgi脚本运行时能看到的$PATH(可选)
    # CGIPath /bin:/usr/bin:/usr/local/bin
    #如果想在任何位置都能运行cgi,要添加这个(可选)
    AddType application/x-httpd-cgi cgi
    # Boa v0.94 configuration file
    # File format has not changed from 0.93
    # File format has changed little from 0.92
    # version changes are noted in the comments
    #
    # The Boa configuration file is parsed with a lex/yacc or flex/bison
    # generated parser. If it reports an error, the line number will be
    # provided; it should be easy to spot. The syntax of each of these
    # rules is very simple, and they can occur in any order. Where possible
    # these directives mimic those of NCSA httpd 1.3; I saw no reason to 
    # introduce gratuitous differences.
    
    # $Id: boa.conf,v 1.25 2002/03/22 04:33:09 jnelson Exp $
    # The "ServerRoot" is not in this configuration file. It can be compiled
    # into the server (see defines.h) or specified on the command line with
    # the -c option, for example:
    #
    # boa -c /usr/local/boa
    
    # Port: The port Boa runs on. The default port for http servers is 80.
    
    # If it is less than 1024, the server must be started as root.
    # 端口老是被占用,所以我改掉了
    Port 88
    
    # Listen: the Internet address to bind(2) to. If you leave it out,
    # it takes the behavior before 0.93.17.2, which is to bind to all
    # addresses (INADDR_ANY). You only get one "Listen" directive,
    # if you want service on multiple IP addresses, you have three choices:
    # 1. Run boa without a "Listen" directive
    # a. All addresses are treated the same; makes sense if the addresses
    # are localhost, ppp, and eth0.
    # b. Use the VirtualHost directive below to point requests to different
    # files. Should be good for a very large number of addresses (web
    # hosting clients).
    # 2. Run one copy of boa per IP address, each has its own configuration
    # with a "Listen" directive. No big deal up to a few tens of addresses.
    # Nice separation between clients.
    # The name you provide gets run through inet_aton(3), so you have to use dotted
    # quad notation. This configuration is too important to trust some DNS.
    
    #Listen 192.68.0.5
    # User: The name or UID the server should run as.
    # Group: The group name or GID the server should run as.
    
    User 0 
    Group 0
    
    # ServerAdmin: The email address where server problems should be sent.
    # Note: this is not currently used, except as an environment variable
    # for CGIs.
    #ServerAdmin root@localhost
    # ErrorLog: The location of the error log file. If this does not start
    # with /, it is considered relative to the server root.
    # Set to /dev/null if you don't want errors logged.
    # If unset, defaults to /dev/stderr
    
    ErrorLog /var/log/boa/error_log
    
    # Please NOTE: Sending the logs to a pipe ('|'), as shown below,
    # is somewhat experimental and might fail under heavy load.
    # "Usual libc implementations of printf will stall the whole
    # process if the receiving end of a pipe stops reading."
    #ErrorLog "|/usr/sbin/cronolog --symlink=/var/log/boa/error_log /var/log/boa/error-%Y%m%d.log"
    
    # AccessLog: The location of the access log file. If this does not
    # start with /, it is considered relative to the server root.
    # Comment out or set to /dev/null (less effective) to disable 
    # Access logging.
    # AccessLog /var/log/boa/access_log
    # Please NOTE: Sending the logs to a pipe ('|'), as shown below,
    # is somewhat experimental and might fail under heavy load.
    # "Usual libc implementations of printf will stall the whole
    # process if the receiving end of a pipe stops reading."
    #AccessLog "|/usr/sbin/cronolog --symlink=/var/log/boa/access_log /var/log/boa/access-%Y%m%d.log"
    
    # UseLocaltime: Logical switch. Uncomment to use localtime 
    # instead of UTC time
    #UseLocaltime
    
    # VerboseCGILogs: this is just a logical switch.
    # It simply notes the start and stop times of cgis in the error log
    # Comment out to disable.
    
    #VerboseCGILogs
    
    # ServerName: the name of this server that should be sent back to 
    # clients if different than that returned by gethostname + gethostbyname
    
    ServerName www.your.org.here
    
    # VirtualHost: a logical switch.
    # Comment out to disable.
    # Given DocumentRoot /var/www, requests on interface 'A' or IP 'IP-A'
    # become /var/www/IP-A.
    # Example: http://localhost/ becomes /var/www/127.0.0.1
    #
    # Not used until version 0.93.17.2. This "feature" also breaks commonlog
    # output rules, it prepends the interface number to each access_log line.
    # You are expected to fix that problem with a postprocessing script.
    
    #VirtualHost
    
    # DocumentRoot: The root directory of the HTML documents.
    # Comment out to disable server non user files.
    
    DocumentRoot /var/www
    
    # UserDir: The name of the directory which is appended onto a user's home
    # directory if a ~user request is recieved.
    
    UserDir public_html
    
    # DirectoryIndex: Name of the file to use as a pre-written HTML
    # directory index. Please MAKE AND USE THESE FILES. On the
    # fly creation of directory indexes can be _slow_.
    # Comment out to always use DirectoryMaker
    
    DirectoryIndex index.html
    
    # DirectoryMaker: Name of program used to create a directory listing.
    # Comment out to disable directory listings. If both this and
    # DirectoryIndex are commented out, accessing a directory will give
    # an error (though accessing files in the directory are still ok).
    
    DirectoryMaker /usr/lib/boa/boa_indexer
    
    # DirectoryCache: If DirectoryIndex doesn't exist, and DirectoryMaker
    # has been commented out, the the on-the-fly indexing of Boa can be used
    # to generate indexes of directories. Be warned that the output is 
    # extremely minimal and can cause delays when slow disks are used.
    # Note: The DirectoryCache must be writable by the same user/group that 
    # Boa runs as.
    
    # DirectoryCache /var/spool/boa/dircache
    
    # KeepAliveMax: Number of KeepAlive requests to allow per connection
    # Comment out, or set to 0 to disable keepalive processing
    
    KeepAliveMax 1000
    
    # KeepAliveTimeout: seconds to wait before keepalive connection times out
    
    KeepAliveTimeout 10
    
    # MimeTypes: This is the file that is used to generate mime type pairs
    # and Content-Type fields for boa.
    # Set to /dev/null if you do not want to load a mime types file.
    # Do *not* comment out (better use AddType!)
    
    MimeTypes /etc/mime.types
    
    # DefaultType: MIME type used if the file extension is unknown, or there
    # is no file extension.
    
    DefaultType text/plain
    
    # CGIPath: The value of the $PATH environment variable given to CGI progs.
    
    CGIPath /bin:/usr/bin:/usr/local/bin
    
    # SinglePostLimit: The maximum allowable number of bytes in 
    # a single POST. Default is normally 1MB.
    
    # AddType: adds types without editing mime.types
    # Example: AddType type extension [extension ...]
    
    # Uncomment the next line if you want .cgi files to execute from anywhere
    #AddType application/x-httpd-cgi cgi
    
    # Redirect, Alias, and ScriptAlias all have the same semantics -- they
    # match the beginning of a request and take appropriate action. Use
    # Redirect for other servers, Alias for the same server, and ScriptAlias
    # to enable directories for script execution.
    
    # Redirect allows you to tell clients about documents which used to exist in
    # your server's namespace, but do not anymore. This allows you to tell the
    # clients where to look for the relocated document.
    # Example: Redirect /bar http://elsewhere/feh/bar
    
    # Aliases: Aliases one path to another.
    # Example: Alias /path1/bar /path2/foo
    
    Alias /doc /usr/doc
    
    # ScriptAlias: Maps a virtual path to a directory for serving scripts
    # Example: ScriptAlias /htbin/ /www/htbin/
    
    ScriptAlias /cgi-bin/ /var/www/cgi-bin/
    View Code

    cgi我的配置:sudo vi /etc/apache2/sites-enabled/000-default

    ServerName 127.0.0.1 
    <VirtualHost *:80>
    ServerAdmin webmaster@localhost
    
    DocumentRoot /var/www
    <Directory />
    Options FollowSymLinks
    AllowOverride None
    </Directory>
    <Directory /var/www/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
    </Directory>
    
    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
    <Directory "/usr/lib/cgi-bin">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny 
    Allow from all
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/error.log
    
    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn
    
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    
    Alias /doc/ "/usr/share/doc/"
    <Directory "/usr/share/doc/">
    Options Indexes MultiViews FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
    Allow from 127.0.0.0/255.0.0.0 ::1/128
    </Directory>
    
    </VirtualHost> 
    View Code

    # 三、调试运行
        都配好后运行 sudo ./boa
        访问 http://127.0.0.1:端口号
        我的就是 http://127.0.0.1:88
        gcc -o test.cgi test.c 编译生成 test.cgi
        把cgi文件拷贝到 cgi-bin 下
        网址就是 http://localhost:88/cgi-bin/test.cgi

     

    # 四、测试源码参考



    下面提供几个测试代码,转自其他大佬,不过我找不到网址了。
    1、

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        char *data;
        long m,n;
        printf("Content-type:text/html
    
    ");
        printf("<HTML>");
        printf("<HEAD>");
        printf("<TITLE>multi</TITLE>");
        printf("</HEAD>");
        printf("<BODY>");
        printf("<H2 ALIGN="center">multi control</H2>");
        printf("<FORM METHOD="GET" ACTION="test1.cgi">");
        printf("<P>Direction:<INPUT TYPE="text" NAME="m" VALUE="" size="18">");
        printf("<P>Step Number:<INPUT TYPE="text" NAME="n" VALUE="" size="17">");
        printf("<P ALIGN="left">");
        printf("<INPUT TYPE="SUBMIT"  VALUE="Submit">");
        printf("<INPUT TYPE="RESET"    VALUE="Reset">");
        printf("</P>");
        printf("</FORM>");
        printf("</BODY>");
        printf("</HTML>");
    
        data=getenv("QUERY_STRING");
        if(!data)
            printf("<P>get no datas and it's wrong.");
        else if(sscanf(data,"m=%ld&n=%ld",&m,&n)!=2)
            printf("<P>the input must be numbers");
        else
            printf("<P>%ld and %ld multi= %ld",m,n,m*n);
        return 0;
    }


    2、
    /var/www 下的pass.html

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>用户登陆验证</title>
    </head>
    <body>
    <form name="form1" action="/cgi-bin/pass.cgi" method="POST">
    <table align="center">
    <tr><td align="center" colspan="2"></td></tr>
    <tr>
    <td align="right">用户名</td>
    <td><input type="text" name="Username"></td>
    </tr>
    <tr>
    <td align="right">密 码</td>
    <td><input type="password" name="Password"></td>
    </tr>
    <tr>
    <td><input type="submit" value="登 录"></td>
    <td><input type="reset" value="取 消"></td>
    </tr>
    </table>
    </form>
    </body>
    </html>

    /var/www/cgi-bin 下的pass.c

    /*=====================================================================
    cgi例子
    =====================================================================*/
    //pass.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    char* getcgidata(FILE* fp, char* requestmethod);
    int main()
    {
           char *input;
           char *req_method;
           char name[64];
           char pass[64];
           int i = 0;
           int j = 0;
          
    //     printf("Content-type: text/plain; charset=iso-8859-1
    
    ");
           printf("Content-type: text/html
    
    ");
           printf("The following is query reuslt:<br><br>");
           req_method = getenv("REQUEST_METHOD");
           input = getcgidata(stdin, req_method);
           // 我们获取的input字符串可能像如下的形式
           // Username="admin"&Password="aaaaa"
           // 其中"Username="和"&Password="都是固定的
           // 而"admin"和"aaaaa"都是变化的,也是我们要获取的
          
           // 前面9个字符是UserName=
           // 在"UserName="和"&"之间的是我们要取出来的用户名
           for ( i = 9; i < (int)strlen(input); i++ )
           {
                  if ( input[i] == '&' )
                  {
                         name[j] = '';
                         break;
                  }                  
                  name[j++] = input[i];
           }
           // 前面9个字符 + "&Password="10个字符 + Username的字符数
           // 是我们不要的,故省略掉,不拷贝
           for ( i = 19 + strlen(name), j = 0; i < (int)strlen(input); i++ )
           {
                  pass[j++] = input[i];
           }
           pass[j] = '';
           printf("Your Username is %s<br>Your Password is %s<br> 
    ", name, pass);
          
           return 0;
    }
    char* getcgidata(FILE* fp, char* requestmethod)
    {
           char* input;
           int len;
           int size = 1024;
           int i = 0;
          
           if (!strcmp(requestmethod, "GET"))
           {
                  input = getenv("QUERY_STRING");
                  return input;
           }
           else if (!strcmp(requestmethod, "POST"))
           {
                  len = atoi(getenv("CONTENT_LENGTH"));
                  input = (char*)malloc(sizeof(char)*(size + 1));
                 
                  if (len == 0)
                  {
                         input[0] = '';
                         return input;
                  }
                 
                  while(1)
                  {
                         input[i] = (char)fgetc(fp);
                         if (i == size)
                         {
                                input[i+1] = '';
                                return input;
                         }
                        
                         --len;
                         if (feof(fp) || (!(len)))
                         {
                                i++;
                                input[i] = '';
                                return input;
                         }
                         i++;
                        
                  }
           }
           return NULL;
    }

    效果图:

    输入数据点击“登录”

    自动跳转到 /cgi-bin/pass.cgi ,获取到数据并打印

    # 五、常见错误
    你的配置会影响网址,502什么错误也是配置或权限有问题导致的。
    如:
    502 Bad Gateway
    The CGI was not CGI/1.1 compliant.
    cgi_header: unable to find LFLF
    1.可能是网址打错了(路径是否和配置文件对应)
    2.配置有问题
    3.权限没给足 chmod 777 test.cgi

    # 六、扩展(CCGI,SQLite)
    CGIC的主站点: http://www.boutell.com/cgic/
    SQLite官网:http://www.sqlite.org/
    配置参考大佬博客:项目实战
    我在调试中遇到的问题也在大佬的博客下面做了 评论 ,如果大家碰到问题可以参考一下。
    补充:编译时会出错,使用

    gcc -o config.cgi config.c sqlite3.c cgic.c -lsqlite3 -lpthread -ldl

    ![涉及文件]


    ![html效果]


    ![cgi页面]


    数据已写入数据库,可使用以下命令

    sqlite3 person.db
    .table
    select * from person;
  • 相关阅读:
    Pascal's Triangle II
    Pascal's Triangle
    Best Time to Buy and Sell Stock II
    Best Time to Buy and Sell Stock
    Populating Next Right Pointers in Each Node
    path sum II
    Path Sum
    [转载]小波时频图
    [转载]小波时频图
    [转载]Hilbert变换及谱分析
  • 原文地址:https://www.cnblogs.com/ikaros-521/p/11698520.html
Copyright © 2011-2022 走看看