• fastcgi+lighttpd+c语言 实现搜索输入提示


    1.lighttpd 服务器

    lighttpd是一个比较轻量的服务器,在运行fastcgi上效率较高。lighttpd只负责投递请求到fastcgi。

    centos输入yum install lighttpd安装  

    2.fastcgi

    fastcgi解决了cgi程序处理请求每次都要初始化和结束造成的性能问题。fastcgi并且是独立于webserver的,fastcgi的crash并不影响webserver,然后他们之间通过soket通信。与fastcgi不同的另一种解决cgi程序反复创建,销毁的方法是让webserver开放api,然后编写cgi的时候,把cgi嵌入到webserver中,这样有个不好的地方就是cgi的crash会影响到webserver。

    支持fastcgi的服务器有很多比如,nginx IIS什么的。他们都是把http请求转换为stdin和一些环境变量传递给fastcgi程序,然后返回stdout。编写fastcgi程序最终要的一个api就是int FCGI_Accept(void);当一个请求被送达的时候返回。一个基本的fastcgi结构如下。

    echo.c

    #include "fcgi_stdio.h"
    #include <stdlib.h>
    
    void main(void)
    {
        //初始化一些全局变量,这里只在fastcgi启动时候运行一次
        while(FCGI_Accept() >= 0)  {
            //fastcgi的处理逻辑
    
            //根据http协议返回处理结果
            printf("Content-type: text/html
    ");
            printf("
    ");
            printf("hello world");
         }
    }

    3.编译echo.c

    编译时候首先要安装fastcti

    wget http://www.fastcgi.com/dist/fcgi.tar.gz

    tar -zxvf fcgi.tar.gz

    cd fcgi-2.4.1-SNAP-0311112127/

    ./configure --prefix=/etc/fcgi

    make && make install

    出现fcgio.cpp:50: error: 'EOF' was not declared in this scope的话 在/include/fcgio.h文件中加上 #include <cstdio>

    到此就安装完了。然后我们来编译echo.c

    gcc echo.c -o echo.cgi -I/etc/fcgi/include -L/etc/fcgi/lib/ -lfcgi

    注意-I -L -l都不能少。

    4.lighttpd+fastcgi配置

    lighttpd支持fastcgi需要安装fastcgi模块

    yum install lighttpd-fastcgi

     

    创建配置文件 vim /etc/fcgi/fcgi.conf

    server.document-root = "/var/www/cgi-bin/"
    server.port = 8080
    server.username = "www-data"
    server.groupname = "www-data"
    server.modules = ("mod_access", "mod_accesslog", "mod_fastcgi")
    server.errorlog = "/var/www/cgi-bin/error.log"
    accesslog.filename = "/var/www/cgi-bin/access.log"
    static-file.exclude-extensions = (".cgi" )
    fastcgi.debug = 1
    fastcgi.server = (
        "echo.cgi" => ((
            "host" => "127.0.0.1",
            "port" => "9000",
            "bin-path" => "/var/www/cgi-bin/echo.cgi",
        ))
    )

    lighttpd -D -f fcgi.conf 时候会出现error while loading shared libraries: libfcgi.so.0: cannot open shared object file: No such file or directory
    反正就是找不到动态链接库,比较无脑的方式就是把fastcgi安装目录下的include和lib都拷贝到/usr/include 和 /usr/lib中。注意,不是/usr/local

    设置过之后可能还是找不到,参考网上另一种方法是。

    首先vim /etc/ld.so.conf 添加libfcgi.so.0的路径,然后运行/sbin/ldconfig,重新编译trie.cgi,ldd trie.cgi一下,看到libfcgi.so.0找到就OKAY了。


    在浏览器输入http://127.0.0.1:8080/echo.cgi 就可以看到hello world了

    5.实例 输入提示

    输入提示的具体实现方法已经在这篇博客里说过 http://www.cnblogs.com/23lalala/p/3513492.html

    这次把他通过fastcgi的api改写成fastcgi程序。
    trie.c

    #include "stdio.h"
    #include "stdlib.h"
    #include "string.h"
    #include "malloc.h"
    #include "fcgi_stdio.h"
    
    char* strcatch(char *str, char ch) {
        char *p = str;
        while (*p!='') {
            p++;
        }
        *p = ch;
        *(p+1) = '';
        return str;
    }
    
    #define MAX_NODE 100000
    #define ALPHA_COUNT 128
    
    typedef struct t_trie{
        int ch[MAX_NODE][ALPHA_COUNT];
        int val[MAX_NODE];
        int size;
    }trie;
    
    trie* create() {
        trie *root = (trie *)malloc(sizeof(trie));
        root->size = 1;
        memset(root->ch[0], 0, sizeof(root->ch[0]));
        return root;
    }
    
    void insert(trie *root, char *str, int n) {
        int i, cur = 0, pre = cur;
        for (i=0; i<n; i++) {
            int c = str[i]-'';
            if (!root->ch[cur][c]) {
                memset(root->ch[root->size], 0, sizeof(root->ch[root->size]));
                root->val[root->size] = 0;
                root->ch[cur][c] = root->size++;
            }
            cur = root->ch[cur][c];
        }
        root->val[cur] = 1;
    }
    
    int search(trie *root, char *str) {
        int i, cur = 0, n = strlen(str);
        for (i=0; i<n; i++) {
            int c = str[i]-'';
            cur = root->ch[cur][c];
        }
        if (root->val[cur]) {
            return 1;
        }
        return 0;
    }
    
    void suggest_helper(trie *root, char* str, int cur, int i, int *count) {
        if (*count > 9) {
            return;
        }
        if (root->val[cur]) {
            *count = *count+1;
            char c = i+'';
            printf("<li onclick="fill('%s%c')">%s%c</li>", str, c, str, c);
        }
        int j=0;
        for (j=0; j<ALPHA_COUNT; j++) {
            if (root->ch[cur][j]) {
                char c = i+'';
                char temp[128];
                strcpy(temp, str);
                strcatch(temp, c);
                suggest_helper(root, temp, root->ch[cur][j], j, count);
            }
        }
    }
    
    void suggest(trie *root, char *str) {
        int i, cur = 0, n = strlen(str), count=0;
        for (i=0; i<n; i++) {
            int c = str[i] - '';
            if (root->ch[cur][c]) {
                cur = root->ch[cur][c];    
            } else {
                printf("no suggestion found
    ");
                return;
            }
        }
        for (i=0; i<ALPHA_COUNT; i++) {
            if (root->ch[cur][i]) {
                suggest_helper(root, str, root->ch[cur][i], i, &count);
            }
        }
    }
    
    int http_get(char *key, char *query, char *result) {
        char *p = result;
        query = strstr(query, key);
        int write = 0;
        while (*query) {
            if (*query=='=') {
                query++;
                write = 1;
                continue;
            }
            if (write) {
                if (*query=='&') {
                    *p = '';
                    return 1;
                }
                *p = *query;
                p++;query++;
            } else {
                query++;
            }
        }
        *p = '';
        return 1;
    }
    
    
    int main() {
        trie *root = create();
        char ch;
        FILE *fp;
        char line[255];
        size_t len = 0;
        ssize_t read;
        char keyword[64];
        if ((fp = fopen("phpfunc.txt", "r")) == NULL) {
            printf("open error
    ");
            exit(1);
        }
        while (fgets(line, 255, fp) != NULL) {
            char *end = strchr(line,'
    ');
            *end = '';
            insert(root, line, strlen(line));
        }
        while (FCGI_Accept() >= 0) {
            printf("Content-Type:text/html; charset=utf-8
    
    ");
            char *query = getenv("QUERY_STRING");
            http_get("q", query, keyword);
            suggest(root, keyword);
        }
        return 0;
    }

    然后编译gcc trie.c -o trie.cgi -I/etc/fcgi/include -L/etc/fcgi/lib/ -lfcgi

    修改fcgi.conf

    fastcgi.server = (
        "trie.cgi" => ((
            "host" => "127.0.0.1",
            "port" => "9000",
            "bin-path" => "/var/www/cgi-bin/trie.cgi",
        ))
    )

    在浏览器输入http://127.0.0.1:8080/trie.cgi?q=var

    可以看到输出var_dump:var_export:variant_abs:variant_add:variant_and:variant_cast:variant_cat:variant_cmp:variant_date_from_timestamp:variant_date_to_timestamp:

    下面是编写前端JS请求

     index.html

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Ajax Auto Suggest</title>
    <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js"></script>
    <script type="text/javascript">
    function lookup(inputString) {
        $.get("http://192.168.2.165:8880/trie.cgi", {q: ""+inputString+""}, function(data){
            if(data.length >0) {
                $('#suggestions').show();
                $('#autoSuggestionsList').html(data);
            }    
        });
    }
    
    function fill(thisValue) {
        $('#inputString').val(thisValue);
        setTimeout("$('#suggestions').hide();", 200);
    }
    </script>
    <style type="text/css">
        body {
            font-family: Helvetica;
            font-size: 11px;
        }
        h3 {
            margin: 0px;
            padding: 0px;    
        }
        .suggestionsBox {
            position: relative;
            left: 30px;
            margin: 10px 0px 0px 0px;
            width: 200px;
            -moz-border-radius: 7px;
            -webkit-border-radius: 7px;
            border: 2px solid #000;    
        }
        .suggestionList {
            margin: 0px;
            padding: 0px;
        }
        .suggestionList li {
            margin: 0px 0px 3px 0px;
            padding: 3px;
            cursor: pointer;
        }
        .suggestionList li:hover {
            background-color: #659CD8;
        }
    </style>
    </head>
    <body>
        <div>
            <form>
                <div>
                    Type php functions:
                    <br />
                    <input type="text" size="30" value="" id="inputString" onkeyup="lookup(this.value);" onblur="fill();" />
                </div>
                <div class="suggestionsBox" id="suggestions" style="display: none;">
                    <img src="upArrow.png" style="position: relative; top: -12px; left: 30px;" alt="upArrow" />
                    <div class="suggestionList" id="autoSuggestionsList">
                    </div>
                </div>
            </form>
        </div>
    </body>
    </html>

    因为服务器需要解析html文件所以在fcgi.conf中添加

    mimetype.assign = (
      ".html" => "text/html",
    )

    启动lighttpd sudo /usr/local/webserver/lighttpd/sbin/lighttpd -D -f /usr/local/webserver/lighttpd/conf/fcgi.conf

    在浏览器输入http://127.0.0.1:8080/index.html 就可以访问了。

    fastcgi,swoole都一定程度弥补了php这种对于开发者类似CGI模式(如果不写PHP扩展,实际就是CGI模式~)对于开发者在开发网站时候的诸多不足。下一篇会介绍thrift并且用thrift编写一个主键生成服务器。

  • 相关阅读:
    毛皮立方体
    APPLE buSinEss
    #4613. problem C
    #4614. problem B
    idiots
    熊猫(i)
    圆盘自动机 cell
    小L的占卜
    有趣的数(number)
    「JOISC 2015 Day 1」卡片占卜
  • 原文地址:https://www.cnblogs.com/23lalala/p/3527354.html
Copyright © 2020-2023  润新知