zoukankan      html  css  js  c++  java
  • nginx—fastcgi—Writing Hello World in FCGI with C++—in CentOS7

    http://chriswu.me/blog/writing-hello-world-in-fcgi-with-c-plus-plus/

    March 23, 2012

    Prerequisites

    This post will assume some familiarity with C++. The setup instructions also assume the server to deploy to is Ubuntu. This tutorial can be applied to other operating systems but I do not provide instructions on installing libraries on other operating systems.

    Why FCGI?

    FCGI (FastCGI) is a protocol in which web applications can talk to a web server to serve web requests. Long story short FCGI was developed to solve the scalability shortcomings that CGI. Typical CGI applications will fork a new process to deal with the request. While this is convenient, it is terribly inefficient due to the overhead of creating and terminating a process for each web request. The idea with FCGI is that you can spawn a static number of processes to handle web requests. This allows for the overhead of creating and terminating processes to be eliminated as resources for request handling can be reused within one process handling multiple requests.

    FCGI easily allows for our application to accept web requests by interacting with stdio. There are alternatives such as implementing your own http server using tools like boost. Simple interface and robust are two of the key points of using fcgi for developing web applications in C++.

    There are more reasons to use fcgi but you can check out the official site and the wikipedia page for more info.

    Installation

    We will need to install the libfcgi++ library, a web server (nignx in our case) and spawn-fcgi to run the fcgi app. We’ll also install curl to help test later on.

    sudo apt-get install libfcgi-dev  sudo apt-get install spawn-fcgi  sudo apt-get install nginx  sudo apt-get install curl

    The Code

    Most of this code is basically a copy paste re-interpretation of the example echo-cpp.cpp from fastcgi.com


    点击(此处)折叠或打开

    1. #include <iostream>
    2. #include "fcgio.h"

    3. using namespace std;

    4. int main(void) {
    5.     // Backup the stdio streambufs
    6.     streambuf * cin_streambuf = cin.rdbuf();
    7.     streambuf * cout_streambuf = cout.rdbuf();
    8.     streambuf * cerr_streambuf = cerr.rdbuf();

    9.     FCGX_Request request;

    10.     FCGX_Init();
    11.     FCGX_InitRequest(&request, 0, 0);

    12.     while (FCGX_Accept_r(&request) == 0) {
    13.         fcgi_streambuf cin_fcgi_streambuf(request.in);
    14.         fcgi_streambuf cout_fcgi_streambuf(request.out);
    15.         fcgi_streambuf cerr_fcgi_streambuf(request.err);

    16.         cin.rdbuf(&cin_fcgi_streambuf);
    17.         cout.rdbuf(&cout_fcgi_streambuf);
    18.         cerr.rdbuf(&cerr_fcgi_streambuf);

    19.         cout << "Content-type: text/html "
    20.              << " "
    21.              << "<html> "
    22.              << " <head> "
    23.              << " <title>Hello, World!</title> "
    24.              << " </head> "
    25.              << " <body> "
    26.              << " <h1>Hello, World!</h1> "
    27.              << " </body> "
    28.              << "</html> ";

    29.         // Note: the fcgi_streambuf destructor will auto flush
    30.     }

    31.     // restore stdio streambufs
    32.     cin.rdbuf(cin_streambuf);
    33.     cout.rdbuf(cout_streambuf);
    34.     cerr.rdbuf(cerr_streambuf);

    35.     return 0;
    36. }

    Breaking code dump down we see that the de-facto interface to stdio (cout/cin/cerr) are hijacked to serve the purposes of request handling. It’s possible to retrieve the iostreams back since we save the stdio stream buffers.

    We then initialize the FCGX library with FCGX_Init() and initialize the request object that we share across requests for the lifetime of this process.

    We then have a blocking loop accepting fcgi requests with our call to FCGX_Accept_r. The _r version calls the multi-thread safe version of the function, although this is not necessary in our single threaded program. This will cleanup the old request that was passed into FCXG_Accept_r and initialize the new request when it comes in.

    We construct the fcgi stream buffers inside the loop, using RAII pattern to ensure the buffers are flushed at the end of the request processing (end of the loop)

    Nginx Config

    Next up we’ll setup nginx to listen on port 80 for http requests and forward those along the the fcgi process which will listen on port 8000.

    The key directive is fastcgi_pass 127.0.0.1:8000 indicates that nginx should forward the fcgi request to port 8000 at localhost. You can replace the address with an upstream directive if you want to want to load balance across many processes. The rest of the fastcgi_param directives are optional and just set appropriate environment variables which get forwarded to the fcgi application.


    点击(此处)折叠或打开

    1. events {
    2.   worker_connections 1024;
    3. }

    4. http {
    5.   server {
    6.     listen 80;
    7.     server_name localhost;

    8.     location / {
    9.       fastcgi_pass 127.0.0.1:8000;

    10.       fastcgi_param GATEWAY_INTERFACE CGI/1.1;
    11.       fastcgi_param SERVER_SOFTWARE nginx;
    12.       fastcgi_param QUERY_STRING $query_string;
    13.       fastcgi_param REQUEST_METHOD $request_method;
    14.       fastcgi_param CONTENT_TYPE $content_type;
    15.       fastcgi_param CONTENT_LENGTH $content_length;
    16.       fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    17.       fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    18.       fastcgi_param REQUEST_URI $request_uri;
    19.       fastcgi_param DOCUMENT_URI $document_uri;
    20.       fastcgi_param DOCUMENT_ROOT $document_root;
    21.       fastcgi_param SERVER_PROTOCOL $server_protocol;
    22.       fastcgi_param REMOTE_ADDR $remote_addr;
    23.       fastcgi_param REMOTE_PORT $remote_port;
    24.       fastcgi_param SERVER_ADDR $server_addr;
    25.       fastcgi_param SERVER_PORT $server_port;
    26.       fastcgi_param SERVER_NAME $server_name;
    27.     }
    28.   }
    29. }

    Running the code

    The system now comprises of three parts. One will be the executable fcgi c++ app. In order to run this we need spawn-fcgi and to listen to a port. Nginx will then forward web requests to this port, translating the http proctocol into the fast cgi protocol.


    点击(此处)折叠或打开

    1. # run nginx using the provided configuration
    2. sudo nginx -c < path to nginx.conf>

    3. # compile hello_world
    4. g++ main_v1.cpp -lfcgi++ -lfcgi -o hello_world

    5. # spawn the fcgi app on port 8000 with no fork
    6. spawn-fcgi -p 8000 -n hello_world
    Then just head to the browser and enter http://localhost/ into the location bar and voilà! Hello, World! See the next part in this tutorial to see how to incorporate the request uri and the request content into this simple app.





    <script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
    阅读(207) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~
    评论热议
  • 相关阅读:
    常用Git命令清单
    上海金瑢信息有限公司面试
    上海视频面试
    bootstrp-3.0
    B站小姐姐面试分享2
    B站小姐姐分享第一次电话面试
    Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组。
    findIndex
    es5,es6
    es6数组去重
  • 原文地址:https://www.cnblogs.com/ztguang/p/12649408.html
Copyright © 2011-2022 走看看