Announcement

Collapse
No announcement yet.

need advice on CGI for PBwin

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • need advice on CGI for PBwin

    I'm setting up a large database application in PB, and I've worked up a method to generate the HTML I need for displaying the screens in HTML. I have plenty of experience with basic programming, database programming, and with simple HTML programming (sufficient for this project). However, I lack greatly in experience in CGI, HTTP, and so on. I did a whole day of research and decided on FastCGI as my solution (I didn't care for the philosophy behind the features in NET.ASP and some of the other solutions, I like to get to the most basic tools aside from Microsoft philosophy, and to me that is FastCGI), and now I'm looking for the best http server to host the site, and the right way to setup the FastCGI executable from PBwin. I only have a general idea on how data is passed from the http server to the FastCGI process, no real specific details.

    Also, I'm trying to setup my development machine to test the CGI as I develop it, so it will need to be both the client and the server. Here is my list of questions:

    1) In order to test a user form going from HTML to FastCGI(inPBwin), and displaying a dynamic response page, do I have to install an http server? Or can I test it without one?

    2) If I need an http server for testing, then is it already in my Vista Ultimate? Or do I need to buy something? Or is there a recommended free alternative? And, will it run offline (no internet connection), for local testing purposes only?

    3) To expand on question #1, is there a client side environment variable that contains the browser's post or query command contents? If so then I can bipass the cgi for now and grab the data there (to locally test the other programming I'm doing), however, even if that works, I don't know how to get the browser to automically view the response, so most likely I can't completely cut CGI from the test loop. I hope someone can elaborate on this point, if there's a solution to this.

    4) I am designing this to handle many simultaneous users, each with a single instance, so my understanding is that this is FastCGI mode #1 (multiple connections, with one instance each). I found the tutorial on the forums for ordinary CGI through PB, it contained an include file, sample HTML, and a sample CGI program. Is there another one for FastCGI through PB? And, if so, then which server will work the best with it? I'm hoping to stick with Windows if possible, but I'm not admitting to it being the best, its just where I'm more familiar.

    5) I will also need to keep the CGI process running (not blocked). I understand blocking between calls is standard, so if there's no way around it then I will have to setup a seperate exe as a service, and access it from the CGI program, so that only the CGI program is blocked. However, it would be nice if this could be handled in the same program. Could I setup a thread that gets blocked while the rest of the program keeps running?

    I guess this is a long post, so I'll stop here.

    Tony
    Tony Snyder

  • #2
    a lot of questions ...

    Originally posted by Tony Snyder View Post
    ... and to me that is FastCGI
    I don't know about FastCGI, but you need a server with a windows operating system on it and the permission to allow CGI-EXE to run.
    A virtual server one will do it, if you don't have too much work on it.
    Smaller Web-Hostings do normaly not allow EXE as CGIs.

    This is a good here http://www.hosteurope.com/

    Originally posted by Tony Snyder View Post
    1) In order to test a user form going from HTML to FastCGI(inPBwin), and displaying a dynamic response page, do I have to install an http server? Or can I test it without one?
    a CGI Programm acts like a filter an DOS :

    echo cInputParameters > CGI.EXE > cHTMLAktion.

    Maybe you can use such a syntax to create HTML pages and open them in a browser, but thats not very usefull. So YES, you will need a html-server (Programm, not a PC).

    Originally posted by Tony Snyder View Post
    2) If I need an http server for testing, then is it already in my Vista Ultimate? Or do I need to buy something? Or is there a recommended free alternative? And, will it run offline (no internet connection), for local testing purposes only?
    I don't habe Vista, but there was a ISS homeserver on Win2000 and WinXP - have a look at the installed software sections. I personaly use the Apache (windows) instead.

    Originally posted by Tony Snyder View Post
    3) To expand on question #1, is there a client side environment variable that contains the browser's post or query command contents? If so then I can bipass the cgi for now and grab the data there (to locally test the other programming I'm doing), however, even if that works, I don't know how to get the browser to automically view the response, so most likely I can't completely cut CGI from the test loop. I hope someone can elaborate on this point, if there's a solution to this.
    The browser will send the data (name=value,...) to the web-server, the web-server will start the exe cgi and sets the environment variables FOR THIS SESSION, that the STARTED CGI.EXE can use it.

    There are some samples here for CGI programming, but normaly you will need the PBCC for that. I think it should be possible to use the PBWin to and open the standard IO filehandles per hand, but I have both so I have never tried.

    PS: you will need a CGI / HTTP Server Test equipment. But you can hold all on 1 PC !

    I don't know anything on question 4.)

    Originally posted by Tony Snyder View Post
    5) I will also need to keep the CGI process running (not blocked). I understand blocking between calls is standard, so if there's no way around it then I will have to setup a seperate exe as a service, and access it from the CGI program, so that only the CGI program is blocked. However, it would be nice if this could be handled in the same program. Could I setup a thread that gets blocked while the rest of the program keeps running?
    Your CGI EXE have to be fast !

    If your CGI connection isn't closed fast enought, the http server will generate an error. But one CGI does normaly not block another (maybe over deadlocks on files ...) and don't forget you will never see anything on a server !

    I must have a look on fastCGI, maybe this is a little different to my normal CGI Programms. I have running some CGI Exes on an old 1.3 GHZ PIII, with DSL (16000/1000 Kbit). It can handle 5 to 10 tasks at the same time per second. If you need more ???
    Regards,
    Hubert

    ------------------------------------
    http://familie-brandel.de/index_e.html

    Comment


    • #3
      I have never tried this but I think to get the STDIN using PBWIN you will need a sequence like this...
      Code:
      FUNCTION PBMain/WinMain 
      
        hSys = GetStdHandle(%STD_INPUT_HANDLE) 
        hIn   = FREEFILE 
        OPEN HANDLE hSys FOR INPUT AS hin 
        WHILE NOT EOF (hIn) 
           LINE INPUT #hIn, aLine$ 
           do something (assemble the document?) 
         WEND 
         CLOSE hin 
         CloseHandle hSys
      You will at point need to create a STDOUT with AllocConsole() to send the response document - or maybe GetStdHandle (%STD_OUTPUT_HANDLE) and OPEN HANDLE that for OUTPUT.

      I honestly don't know if the STDIN, STDOUT and STDERR are always created when your program is started up, but I do know you don't have access to them with PB/Win unless you set it up.

      At least it's some stuff to try.

      Come to think of it.... the standard handles may be available in the STARTUPINFO structure available to your program.


      MCM
      Last edited by Michael Mattias; 9 Sep 2008, 10:39 AM.
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        Originally posted by Tony Snyder View Post

        1) In order to test a user form going from HTML to FastCGI(inPBwin), and displaying a dynamic response page, do I have to install an http server? Or can I test it without one?
        First I am not familiar with the differences in CGI/FastCGI. What I mention is based on my CGI experiments (nothing in production).

        Yes, you will need something to process the incoming requests.

        Originally posted by Tony Snyder View Post
        2) If I need an http server for testing, then is it already in my Vista Ultimate? Or do I need to buy something? Or is there a recommended free alternative? And, will it run offline (no internet connection), for local testing purposes only?

        There are several solutions:
        • Windows version of apache (free)
        • Analogx Simple Server (free version) [Recommended, but not sure if it supports fastCGI]
        • Write your own. You could write your own simple HTTP processor. Doesn't have to be a full blown web server. Just enough to test your application.


        If you are going to host your application you may want to use the same web server version as the host uses. For example, if you host on Windows 2003 with IIS, you could get a virtual machine and set up an copy. Of course this has a cost of at least an OS. Your testing would confirm that it will run in production and you won't have issues with the software not running.

        Originally posted by Tony Snyder View Post
        3) To expand on question #1, is there a client side environment variable that contains the browser's post or query command contents? If so then I can bipass the cgi for now and grab the data there (to locally test the other programming I'm doing), however, even if that works, I don't know how to get the browser to automically view the response, so most likely I can't completely cut CGI from the test loop. I hope someone can elaborate on this point, if there's a solution to this.
        I'd recommend Analogix Simple Server for initial testing. This is small server that can handle CGI applications(not sure about FastCGI though). Simple to configure.

        You could write your own simple set of applications. A client that simulates the requests from the browser and a server that response and calls the CGI application. This would be great for testing the application under load. You could run several client apps (simulating multiple clients and see what the server does under some load). Of course, if you really want to test load, you will need to do so in the real environment.

        Originally posted by Tony Snyder View Post
        4) I am designing this to handle many simultaneous users, each with a single instance, so my understanding is that this is FastCGI mode #1 (multiple connections, with one instance each). I found the tutorial on the forums for ordinary CGI through PB, it contained an include file, sample HTML, and a sample CGI program. Is there another one for FastCGI through PB? And, if so, then which server will work the best with it? I'm hoping to stick with Windows if possible, but I'm not admitting to it being the best, its just where I'm more familiar.
        This sounds like the safest solution. Each connection will run a copy of the CGI application. If for some reason one crashes it won't lock out all other users. There are some caveats though.

        * Each copy will need to initialize access to the database.
        * Each connection/request will restart a new copy. State can't be maintained (at least I don't think so)
        * If you have 100 connections there will be 100 copies of the CGI application running. If the CGI app uses 5 MB of memory, that is 500MB. If it is 20MB, that is 2GB. So keep an eye on resource usage. Having said this I have written a PBCC CGI that used 200K, so 100 connections was 20MB.
        * If a error/crash occurs it could leave resources used/open which will eventually crash the server. i.e. memory leaks or database connections open.

        Originally posted by Tony Snyder View Post
        5) I will also need to keep the CGI process running (not blocked). I understand blocking between calls is standard, so if there's no way around it then I will have to setup a seperate exe as a service, and access it from the CGI program, so that only the CGI program is blocked. However, it would be nice if this could be handled in the same program. Could I setup a thread that gets blocked while the rest of the program keeps running?
        The CGI application needs to respond to the user quickly. You don't want the user waiting 5 to 10 seconds. The user will think the site locked up; if your lucky (or not) they will try again. Also the browser could time out.

        You don't want to keep the CGI app open over multiple requests on the same connection. It would be very simple for the site to be brought to its knees. Imagine receiving 1,000s of requests where each creates a new connection. If the app is 5MB in size, you will quickly run out of memory. Think of each request as a separate atomic connection. Get the request, get the answer, respond, close resources and the app.

        I am not sure of what your planning for your application, but bots like google, Yahoo and others index your site could make many requests.

        Using a separate service for dynamic data is the best way to go.
        • Testing of the service separate from CGI.
        • More scalable. Two or more web servers with the CGI app that communicate to the backend service (on another computer). Of course, this depends on the resource requirements of you huge database.
        • Caching of data In addition, the service would be able to cache data that all connections/requests required instead of having the CGI application having to perform these requests every time.
        • If a hacker does connect generating 1,000s of requests, this only puts a load on the service. The service answers each request and doesn't tie up resources.
        • Of course, there is some data that the server needs to persist. For example who is logged in, logged in since, etc.. This data is maybe 1KB, small enough that if you receive thousands of requests the data won't overrun the server.


        Just a couple things for you to think about.

        Comment


        • #5
          First of all, if you haven't read my CGI tutorials, you should. There are here

          Second. Don't get too hung up on "fastCGI" just yet. It is not always the best solution. It depends greatly on what you are doing. In a nutshell, FastCGI simply keeps your DLLs (and sometimes the executables) in memory so they don't need to be loaded each time. If you have adequate RAM, you may not be buying much in performance anyway.

          Third. Use Abyss as your web server. I've tested 'em all, and Abyss is the champ. It will support FastCGI if you decide to go that route.

          Forth. If this is a commercial venture (you plan to make some $$ from it), buy PBCC. Yes, you can create CGI apps with PBWin but you'll pay for it many times over. Just get the right tool to begin with and be done with it.

          Fifth. Learn how HTML forms interact with the Web server and your CGI application before embarking on a lot of coding. Do a number of small CGI applications until you get the big picture. You'll discover that you'll need to think a bit differently that non-CGI programming.

          Sixth. If you want to do anything beyond basic form functions, you'll really need to know some javascript, the more the better. This is especially true regarding AJAX techniques which you will want to understand well before you begin any big project.
          Software makes Hardware Happen

          Comment


          • #6
            Originally posted by Joe Byrne View Post
            buy PBCC. Yes, you can create CGI apps with PBWin but you'll pay for it many times over. Just get the right tool to begin with and be done with it.
            SO, what does PBCC bring to CGI programming which PBWin does not?

            Comment


            • #7
              Originally posted by Chris Holbrook View Post
              SO, what does PBCC bring to CGI programming which PBWin does not?
              Hi,

              PBCC does have \samples\Internet\CGI\... and the STDIN and STDOUT commands. I have never tried to build these with open .... PBCC ist so cheap and the samples are realy usefull.

              Bye
              Hubert
              Regards,
              Hubert

              ------------------------------------
              http://familie-brandel.de/index_e.html

              Comment


              • #8
                clarification

                Thanks for all the responses. I noticed the first few didn't know about FastCGI, I'll explain a bit here...

                It takes the same basic CGI program and allows it to persist in memory, and the only program change is to separate out the initialization part (including opening databases, etc.), from the loop that responds to the CGI request. Then it sits in memory waiting for a flag to be set by FastCGI (which I think is built into the server somehow). Your CGI sees this flag and runs one iteration of the loop, and is then blocked until the next user request. This way it doesn't tie up the CPU, and its all ready to go with minimal overhead per request. I understand there are several ways to set it up ranging from minimal speed benefit up to about 10x benefit, not to mention the obvious RAM benefit on simultaneous connections. I'm hoping to get as much as possible.

                I'm about 98% convinced that I need to have 2 executables there, a very small CGI, and a separate exe for my main service (much larger), and get them to talk to each other. Then the CGI can start/stop as necessary to support FastCGI, while the rest of the program keeps running the application (dealing with unrelated tasks).

                Anyway, the project is for commercial use, and my expertise is in the application area, with a bit of a learning curve to go through implementing CGI. They do want it to run fast and handle lots of users, so that's the direction I'm taking.

                However, I am in no hurry on the FastCGI part (have until May on that part). Right now I just need to close the loop between HTML and my application for testing purposes on a local development machine with the least effort possible. So I think I'll be looking at whichever server I can download and get running quickly. I see a couple suggestions on these posts, will get to it tomorrow and see what happens.

                Thanks for the help so far.

                Tony
                Tony Snyder

                Comment


                • #9
                  Regarding PBwin versus PBcc

                  Ok, I understand that PBcc is made for this sort of thing, but what exactly are the differences that I will run into? Really, I only plan on making one simple CGI program, that passes data back and forth to my main application. Do I need to purchase PBcc for this to make it easier to program, a faster program, or a more reliable program?
                  Tony Snyder

                  Comment


                  • #10
                    Hi,

                    I think the normal CGIs best thing is, that the short CGI running time for only one simple job separated from the www-server will prevent you from side effects.

                    How many users will use this program at the same time (second !) ?
                    Do we talk about 10 or 35000 per second ?

                    The overhead per CGI EXE is about 1 MB RAM per running EXE. CPU and HD will not have to much work with it.

                    If you have tasks which have to be done time by time, than you should write a server programm running hole the time (maybe more threads and with SLEEP) and use the CGI only to trigger some actions there.
                    Regards,
                    Hubert

                    ------------------------------------
                    http://familie-brandel.de/index_e.html

                    Comment


                    • #11
                      Hi,

                      if you want to know if it is possible, then try out OPEN .... should do if you know the STDIN and STDOUT handle. Then you have to know (or get samples) the way the WWW-SERVER sends the data to the CGI program. Maybe you will get this in 4 hours.

                      Than have a look at the price of PBCC, and think what is more worth ?
                      Regards,
                      Hubert

                      ------------------------------------
                      http://familie-brandel.de/index_e.html

                      Comment


                      • #12
                        I'm about 98% convinced that I need to have 2 executables there, a very small CGI, and a separate exe for my main service (much larger), and get them to talk to each other.
                        First you make it work; only then do you make it work better.
                        Michael Mattias
                        Tal Systems (retired)
                        Port Washington WI USA
                        [email protected]
                        http://www.talsystems.com

                        Comment


                        • #13
                          You can write cgi programs with PBWin
                          http://www.powerbasic.com/support/pb...ight=pbcgiboth
                          FastCGI is similar, but definitely not the same. See include file below.
                          If you can give the users a client program you don't need CGI, but client/server.
                          TTDS using Tsunami or SQLitening might be a better choice.
                          You can have persistant connnections and still display html inside your own custom browser.
                          Timm at http://www.trm-ug.com has another client/server program coming.

                          Like Joe said Abyss is the way to go if you must use FastCgi.
                          If you are going to set up an http server (which you might not need) I'd also make the suggestion
                          of setting it up using a structure that will also work on a remote server so you can move easily.
                          Example: (on you local machine)
                          \home\yourname\www\cgi-bin

                          By following the above you should have no problem moving to a remote server later and you
                          can test everything locally. I found it easier to let a remote ISP handle the server, but I
                          also have a local server that can be switched to at any time using DYNDNS.




                          ----------------------------------------------------------------------------------------------------
                          Code:
                          ' * fcgiapp.h
                          ' * Definitions for FastCGI application server programs
                           
                          ' * Copyright (c) 1996 Open Market, Inc.
                          ' * See the file "LICENSE.TERMS" for information on usage and redistribution
                          ' * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
                          ' * $Id: fcgiapp.h,v 1.12 2001/11/21 21:10:11 robs Exp $
                           
                          #IF NOT %DEF(%FCGIAPP_H)
                          %FCGIAPP_H = 1
                          ' Hack to see if we are building TCL - TCL needs varargs not stdarg
                          '#If Not %Def(%TCL_LIBRARY)
                          '$include "stdarg.h"
                          '#else
                          '$include "varargs.h"
                          '#endif
                          #IF NOT %DEF(%DLLAPI)
                          %DLLAPI = 1
                          #ENDIF
                          ' * Error codes. Assigned to avoid conflict with EOF and errno(2).
                          %FCGX_UNSUPPORTED_VERSION = -2
                          %FCGX_PROTOCOL_ERROR = -3
                          %FCGX_PARAMS_ERROR = -4
                          %FCGX_CALL_SEQ_ERROR = -5
                          MACRO FCGX_ParamArray = DWORD PTR
                          MACRO opt_ = OPTIONAL x AS ANY
                          MACRO etc = opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_,opt_
                          ' * This structure defines the state of a FastCGI stream.
                          ' * Streams are modeled after the FILE type defined in stdio.h.
                          ' * (We wouldn't need our own if platform vendors provided a
                          ' * standard way to subclass theirs.)
                          ' * The state of a stream is private and should only be accessed
                          ' * by the procedures defined below.
                          'typedef struct FCGX_Stream {
                          ' unsigned char *rdNext; /* reader: first valid byte
                          ' * writer: equals stop */
                          ' unsigned char *wrNext; /* writer: first free byte
                          ' * reader: equals stop */
                          ' unsigned char *stop; /* reader: last valid byte + 1
                          ' * writer: last free byte + 1 */
                          ' unsigned char *stopUnget; /* reader: first byte of current buffer
                          ' * fragment, for ungetc
                          ' * writer: undefined */
                          ' int isReader;
                          ' int isClosed;
                          ' int wasFCloseCalled;
                          ' int FCGI_errno; /* error status */
                          ' void (*fillBuffProc) (struct FCGX_Stream *stream);
                          ' void (*emptyBuffProc) (struct FCGX_Stream *stream, int doClose);
                          ' void *data;
                          '} FCGX_Stream;
                          TYPE FCGX_Stream
                          rdNext AS ASCIIZ PTR ' reader: first valid byte
                          wrNext AS ASCIIZ PTR ' writer: first free byte
                          pStop AS ASCIIZ PTR ' reader: last valid byte + 1
                          stopUnget AS ASCIIZ PTR ' reader: first byte of current buffer
                          isReader AS LONG
                          isClosed AS LONG
                          wasFCloseCalled AS LONG
                          FCGI_errno AS LONG ' error status
                          fillBuffProc AS DWORD PTR ' function pointer to FillBuffProc
                          emptyBuffProc AS DWORD PTR ' function pointer to EmptyBuffProc
                          pData AS DWORD PTR
                          END TYPE
                           
                          ' * An environment (as defined by environ(7)): A NULL-terminated array
                          ' * of strings, each string having the form name=value.
                          %FCGI_FAIL_ACCEPT_ON_INTR = 1
                          ' * FCGX_Request -- State associated with a request.
                          ' * Its exposed for API simplicity, I expect parts of it to change!
                          '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;
                          TYPE FCGX_Request
                          requestId AS LONG ' valid if isBeginProcessed
                          role AS LONG
                          pIn AS FCGX_Stream PTR
                          pOut AS FCGX_Stream PTR
                          pErr AS FCGX_Stream PTR
                          envp AS FCGX_ParamArray
                          ' Don't use anything below here
                          paramsPtr AS DWORD
                          ipcFd AS LONG ' < 0 means no connection
                          isBeginProcessed AS LONG ' FCGI_BEGIN_REQUEST seen
                          keepConnection AS LONG ' don't close ipcFd at end of request
                          appStatus AS LONG
                          nWriters AS LONG ' number of open writers (0..2)
                          flags AS LONG
                          listen_sock AS LONG
                          END TYPE
                          ' * Control
                          ' * FCGX_IsCGI
                          ' * Returns TRUE iff this process appears to be a CGI process
                          ' * rather than a FastCGI process.
                          'DLLAPI int FCGX_IsCGI(void);
                          DECLARE FUNCTION FCGX_IsCGI CDECL LIB "fcgi.dll" ALIAS "FCGX_IsCGI" () AS LONG
                           
                          ' * FCGX_Init
                          ' * Initialize the FCGX library. Call in multi-threaded apps
                          ' * before calling FCGX_Accept_r().
                          ' * Returns 0 upon success.
                          'DLLAPI int FCGX_Init(void)
                          DECLARE FUNCTION FCGX_Init CDECL LIB "fcgi.dll" ALIAS "FCGX_Init" () AS LONG
                           
                          ' * FCGX_OpenSocket
                          ' * Create a FastCGI listen socket.
                          ' * path is the Unix domain socket (named pipe for WinNT), or a colon
                          ' * followed by a port number. e.g. "/tmp/fastcgi/mysocket", ":5000"
                          ' * backlog is the listen queue depth used in the listen() call.
                          ' * Returns the socket's file descriptor or -1 on error.
                          'DLLAPI int FCGX_OpenSocket(const char *path, int backlog)
                          DECLARE FUNCTION FCGX_OpenSocket CDECL LIB "fcgi.dll" ALIAS "FCGX_OpenSocket" (path AS ASCIIZ, backlog AS LONG) AS LONG
                          ' * FCGX_InitRequest
                          ' * Initialize a FCGX_Request for use with FCGX_Accept_r().
                          ' * sock is a file descriptor returned by FCGX_OpenSocket() or 0 (default).
                          ' * The only supported flag at this time is FCGI_FAIL_ON_INTR.
                          ' * Returns 0 upon success.
                           
                          'DLLAPI int FCGX_InitRequest(FCGX_Request *request, int sock, int flags)
                          DECLARE FUNCTION FCGX_InitRequest CDECL LIB "fcgi.dll" ALIAS "FCGX_InitRequest" (BYREF request AS FCGX_Request, sock AS LONG, flags AS LONG) AS LONG
                          ' * FCGX_Accept_r
                          ' * Accept a new request (multi-thread safe). Be sure to call
                          ' * FCGX_Init() first.
                          ' * Results:
                          ' * 0 for successful call, -1 for error.
                          ' * Side effects:
                          ' * Finishes the request accepted by (and frees any
                          ' * storage allocated by) the previous call to FCGX_Accept.
                          ' * Creates input, output, and error streams and
                          ' * assigns them to *in, *out, and *err respectively.
                          ' * Creates a parameters data structure to be accessed
                          ' * via getenv(3) (if assigned to environ) or by FCGX_GetParam
                          ' * and assigns it to *envp.
                          ' * DO NOT retain pointers to the envp array or any strings
                          ' * contained in it (e.g. to the result of calling FCGX_GetParam),
                          ' * since these will be freed by the next call to FCGX_Finish
                          ' * or FCGX_Accept.
                          ' * DON'T use the FCGX_Request, its structure WILL change.
                          'DLLAPI int FCGX_Accept_r(FCGX_Request *request)
                          DECLARE FUNCTION FCGX_Accept_r CDECL LIB "fcgi.dll" ALIAS "FCGX_Accept_r" (BYREF request AS FCGX_Request) AS LONG
                           
                          ' * FCGX_Finish_r
                          ' * Finish the request (multi-thread safe).
                          ' * Side effects:
                          ' * Finishes the request accepted by (and frees any
                          ' * storage allocated by) the previous call to FCGX_Accept.
                          ' * DO NOT retain pointers to the envp array or any strings
                          ' * contained in it (e.g. to the result of calling FCGX_GetParam),
                          ' * since these will be freed by the next call to FCGX_Finish
                          ' * or FCGX_Accept.
                          'DLLAPI void FCGX_Finish_r(FCGX_Request *request)
                          DECLARE SUB FCGX_Finish_r CDECL LIB "fcgi.dll" ALIAS "FCGX_Finish_r" (BYREF request AS FCGX_Request)
                          ' * FCGX_Free
                          ' * Free the memory and, if close is true,
                          ' * IPC FD associated with the request (multi-thread safe).
                          'DLLAPI void FCGX_Free(FCGX_Request * request, int close)
                          DECLARE SUB FCGX_Free CDECL LIB "fcgi.dll" ALIAS "FCGX_Free" (BYREF request AS FCGX_Request, lClose AS LONG)
                          ' * FCGX_Accept
                          ' * Accept a new request (NOT multi-thread safe).
                          ' * Results:
                          ' * 0 for successful call, -1 for error.
                          ' * Side effects:
                          ' * Finishes the request accepted by (and frees any
                          ' * storage allocated by) the previous call to FCGX_Accept.
                          ' * Creates input, output, and error streams and
                          ' * assigns them to *in, *out, and *err respectively.
                          ' * Creates a parameters data structure to be accessed
                          ' * via getenv(3) (if assigned to environ) or by FCGX_GetParam
                          ' * and assigns it to *envp.
                          ' * DO NOT retain pointers to the envp array or any strings
                          ' * contained in it (e.g. to the result of calling FCGX_GetParam),
                          ' * since these will be freed by the next call to FCGX_Finish
                          ' * or FCGX_Accept.
                          'DLLAPI int FCGX_Accept(
                          'FCGX_Stream **in,
                          'FCGX_Stream **out,
                          'FCGX_Stream **err,
                          'FCGX_ParamArray *envp)
                          DECLARE FUNCTION FCGX_Accept CDECL LIB "fcgi.dll" ALIAS "FCGX_Accept" ( _
                            pIn AS FCGX_Stream,pOut AS FCGX_Stream,pErr AS FCGX_Stream,pEnvp AS FCGX_ParamArray ) AS LONG
                          ' * FCGX_Finish
                          ' * Finish the current request (NOT multi-thread safe).
                          ' * Side effects:
                          ' * Finishes the request accepted by (and frees any
                          ' * storage allocated by) the previous call to FCGX_Accept.
                          ' * DO NOT retain pointers to the envp array or any strings
                          ' * contained in it (e.g. to the result of calling FCGX_GetParam),
                          ' * since these will be freed by the next call to FCGX_Finish
                          ' * or FCGX_Accept.
                          'DLLAPI void FCGX_Finish(void)
                          DECLARE SUB FCGX_Finish CDECL LIB "fcgi.dll" ALIAS "FCGX_Finish" ()
                          ' * FCGX_StartFilterData
                          ' * stream is an input stream for a FCGI_FILTER request.
                          ' * stream is positioned at EOF on FCGI_STDIN.
                          ' * Repositions stream to the start of FCGI_DATA.
                          ' * If the preconditions are not met (e.g. FCGI_STDIN has not
                          ' * been read to EOF) sets the stream error code to
                          ' * FCGX_CALL_SEQ_ERROR.
                          ' * Results:
                          ' * 0 for a normal return, < 0 for error
                          'DLLAPI int FCGX_StartFilterData(FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_StartFilterData CDECL LIB "fcgi.dll" ALIAS "FCGX_StartFilterData" (stream AS FCGX_Stream PTR) AS LONG
                          ' * FCGX_SetExitStatus
                          ' * Sets the exit status for stream's request. The exit status
                          ' * is the status code the request would have exited with, had
                          ' * the request been run as a CGI program. You can call
                          ' * SetExitStatus several times during a request; the last call
                          ' * before the request ends determines the value.
                          'DLLAPI void FCGX_SetExitStatus(int status, FCGX_Stream *stream)
                          DECLARE SUB FCGX_SetExitStatus CDECL LIB "fcgi.dll" ALIAS "FCGX_SetExitStatus" (lStatus AS LONG, pStream AS FCGX_Stream PTR)
                          ' * Parameters
                          ' * FCGX_GetParam -- obtain value of FCGI parameter in environment
                           
                          ' * Results:
                          ' * Value bound to name, NULL if name not present in the
                          ' * environment envp. Caller must not mutate the result
                          ' * or retain it past the end of this request.
                          'DLLAPI char *FCGX_GetParam(const char *name, FCGX_ParamArray envp)
                          DECLARE FUNCTION FCGX_GetParam CDECL LIB "fcgi.dll" ALIAS "FCGX_GetParam" (pName AS ASCIIZ, envp AS FCGX_ParamArray) AS DWORD
                          ' * Readers
                          ' * FCGX_GetChar
                          ' * Reads a byte from the input stream and returns it.
                          ' * Results:
                          ' * The byte, or EOF (-1) if the end of input has been reached.
                          'DLLAPI int FCGX_GetChar(FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_GetChar CDECL LIB "fcgi.dll" ALIAS "FCGX_GetChar" (pStream AS FCGX_Stream PTR) AS LONG
                          ' * FCGX_UnGetChar
                          ' * Pushes back the character c onto the input stream. One
                          ' * character of pushback is guaranteed once a character
                          ' * has been read. No pushback is possible for EOF.
                          ' * Results:
                          ' * Returns c if the pushback succeeded, EOF if not.
                          'DLLAPI int FCGX_UnGetChar(int c, FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_UnGetChar CDECL LIB "fcgi.dll" ALIAS "FCGX_UnGetChar" (c AS LONG, pStream AS FCGX_Stream PTR) AS LONG
                          ' * FCGX_GetStr
                          ' * Reads up to n consecutive bytes from the input stream
                          ' * into the character array str. Performs no interpretation
                          ' * of the input bytes.
                          ' * Results:
                          ' * Number of bytes read. If result is smaller than n,
                          ' * the end of input has been reached.
                          'DLLAPI int FCGX_GetStr(char *str, int n, FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_GetStr CDECL LIB "fcgi.dll" ALIAS "FCGX_GetStr" (str AS ASCIIZ, n AS LONG, pStream AS FCGX_Stream PTR) AS LONG
                          ' * FCGX_GetLine
                          ' * Reads up to n-1 consecutive bytes from the input stream
                          ' * into the character array str. Stops before n-1 bytes
                          ' * have been read if '\n' or EOF is read. The terminating '\n
                          ' * is copied to str. After copying the last byte into str,
                          ' * stores a '\0' terminator.
                          ' * Results:
                          ' * NULL if EOF is the first thing read from the input stream,
                          ' * str otherwise.
                          'DLLAPI char *FCGX_GetLine(char *str, int n, FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_GetLine CDECL LIB "fcgi.dll" ALIAS "FCGX_GetLine" (str AS ASCIIZ, n AS LONG, pStream AS FCGX_Stream PTR) AS LONG
                           
                          ' * FCGX_HasSeenEOF
                          ' * Returns EOF if end-of-file has been detected while reading
                          ' * from stream; otherwise returns 0.
                          ' * Note that FCGX_HasSeenEOF(s) may return 0, yet an immediately
                          ' * following FCGX_GetChar(s) may return EOF. This function, like
                          ' * the standard C stdio function feof, does not provide the
                          ' * ability to peek ahead.
                          ' * Results:
                          ' * EOF if end-of-file has been detected, 0 if not.
                           
                          'DLLAPI int FCGX_HasSeenEOF(FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_HasSeenEOF CDECL LIB "fcgi.dll" ALIAS "FCGX_HasSeenEOF" (pStream AS FCGX_Stream PTR) AS LONG
                          ' * Writers
                           
                          ' * FCGX_PutChar
                          ' * Writes a byte to the output stream.
                          ' * Results:
                          ' * The byte, or EOF (-1) if an error occurred.
                          'DLLAPI int FCGX_PutChar(int c, FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_PutChar CDECL LIB "fcgi.dll" ALIAS "FCGX_PutChar" (c AS LONG, pStream AS FCGX_Stream PTR) AS LONG
                          ' * FCGX_PutStr
                          ' * Writes n consecutive bytes from the character array str
                          ' * into the output stream. Performs no interpretation
                          ' * of the output bytes.
                          ' * Results:
                          ' * Number of bytes written (n) for normal return,
                          ' * EOF (-1) if an error occurred.
                          'DLLAPI int FCGX_PutStr(const char *str, int n, FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_PutStr CDECL LIB "fcgi.dll" ALIAS "FCGX_PutStr" (str AS ASCIIZ, n AS LONG, pStream AS FCGX_Stream PTR) AS LONG
                          ' * FCGX_PutS
                          ' * Writes a null-terminated character string to the output stream.
                          ' * Results:
                          ' * number of bytes written for normal return,
                          ' * EOF (-1) if an error occurred.
                          'DLLAPI int FCGX_PutS(const char *str, FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_PutS CDECL LIB "fcgi.dll" ALIAS "FCGX_PutS" (str AS ASCIIZ, pStream AS FCGX_Stream PTR) AS LONG
                          ' * FCGX_FPrintF, FCGX_VFPrintF
                          ' * Performs printf-style output formatting and writes the results
                          ' * to the output stream.
                          ' * Results:
                          ' * number of bytes written for normal return,
                          ' * EOF (-1) if an error occurred.
                          'DLLAPI int FCGX_FPrintF(FCGX_Stream *stream, const char *format, ...)
                          DECLARE FUNCTION FCGX_FPrintF CDECL LIB "fcgi.dll" ALIAS "FCGX_FPrintF" (pStream AS FCGX_Stream PTR, format AS ASCIIZ, etc ) AS LONG
                          'DLLAPI int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                           
                          ' * FCGX_FFlush
                          ' * Flushes any buffered output.
                          ' * Server-push is a legitimate application of FCGX_FFlush.
                          ' * Otherwise, FCGX_FFlush is not very useful, since FCGX_Accept
                          ' * does it implicitly. Calling FCGX_FFlush in non-push applications
                          ' * results in extra writes and therefore reduces performance.
                          ' * Results:
                          ' * EOF (-1) if an error occurred.
                          'DLLAPI int FCGX_FFlush(FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_FFlush CDECL LIB "fcgi.dll" ALIAS "FCGX_FFlush" (pStream AS FCGX_Stream PTR) AS LONG
                          ' * Both Readers and Writers
                           
                          ' * FCGX_FClose
                          ' * Closes the stream. For writers, flushes any buffered
                          ' * output.
                          ' * Close is not a very useful operation since FCGX_Accept
                          ' * does it implicitly. Closing the out stream before the
                          ' * err stream results in an extra write if there's nothing
                          ' * in the err stream, and therefore reduces performance.
                          ' * Results:
                          ' * EOF (-1) if an error occurred.
                          'DLLAPI int FCGX_FClose(FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_FClose CDECL LIB "fcgi.dll" ALIAS "FCGX_FClose" (pStream AS FCGX_Stream PTR) AS LONG
                           
                          ' * FCGX_GetError
                          ' * Return the stream error code. 0 means no error, > 0
                          ' * is an errno(2) error, < 0 is an FastCGI error.
                          'DLLAPI int FCGX_GetError(FCGX_Stream *stream)
                          DECLARE FUNCTION FCGX_GetError CDECL LIB "fcgi.dll" ALIAS "FCGX_GetError" (pStream AS FCGX_Stream PTR) AS LONG
                           
                          ' * FCGX_ClearError
                          ' * Clear the stream error code and end-of-file indication.
                          'DLLAPI void FCGX_ClearError(FCGX_Stream *stream)
                          DECLARE SUB FCGX_ClearError CDECL LIB "fcgi.dll" ALIAS "FCGX_ClearError" (pStream AS FCGX_Stream PTR)
                          ' * FCGX_CreateWriter
                          ' * Create a FCGX_Stream (used by cgi-fcgi). This shouldn't
                          ' * be needed by a FastCGI applictaion.
                          'DLLAPI FCGX_Stream *FCGX_CreateWriter(
                          'int socket,
                          'int requestId,
                          'int bufflen,
                          'int streamType)
                          DECLARE FUNCTION FCGX_CreateWriter CDECL LIB "fcgi.dll" ALIAS "FCGX_CreateWriter" ( _
                          socket AS LONG, _
                          requestId AS LONG, _
                          bufflen AS LONG, _
                          streamType AS LONG ) AS DWORD
                          ' * FCGX_FreeStream
                          ' * Free a FCGX_Stream (used by cgi-fcgi). This shouldn't
                          ' * be needed by a FastCGI applictaion.
                          'DLLAPI void FCGX_FreeStream(FCGX_Stream **stream)
                          ' * Prevent the lib from accepting any new requests. Signal handler safe.
                          'DLLAPI void FCGX_ShutdownPending(void)
                          DECLARE SUB FCGX_ShutdownPending CDECL LIB "fcgi.dll" ALIAS "FCGX_ShutdownPending" ()
                          #ENDIF ' FCGIAPP_H
                          Last edited by Mike Doty; 10 Sep 2008, 10:09 PM.

                          Comment


                          • #14
                            next question: getting CGI to talk to another exe

                            Abyss installed quite easily. And a test CGI is running quite well right now as ordinary CGI, and I think I'll stick to that for now and get back to the FastCGI idea after everything else is working. (Once fully operational I expect up to about 500 simultaneous user connections, one instance each.)

                            The issue I'm having now probably needs another thread, how to get the CGI program to rapidly pass data to my other exe? Sounds so simple, back in the DOS world I would just use a common RAM area and peek and poke, and now I see great string peek and poke in PB, but how do I give the address to the other exe? And won't I be violating protected memory issues? Originally I was going to use environment variables for this, but then there's Microsoft's parent-child restrictions. I read in various server specs about local piping, yet there's no piping commands in PB. What do you guys do for ultra fast interexe data handling? Keep in mind the administrator launches my main app exe, and the HTTP server launches the CGI exes, so there's no inheritance there that I can see. However, I'm not very knowledgeable on the inheritance concepts in the first place, never really agreed with the idea. I suppose I could link to TCP but I was hoping for something faster and simpler than that (TCP is designed to work over networks, what I need is always local).

                            Of course another issue is the fact that there will be many CGI instances all talking at once to a single main app instance, but I have that part worked out, once I know what data-passing mechanism to use.
                            Tony Snyder

                            Comment


                            • #15
                              Sharing data across processes with locking:
                              Win32: Memory Mapped Files/Control User Count April 26, 2001

                              Lots of other ways, but why do you have to share with an EXE? Write your 'other' program as a DLL and just pass the data as parameters. Use multiple threads of execution to service many users at once without them stepping on each others' data.
                              Michael Mattias
                              Tal Systems (retired)
                              Port Washington WI USA
                              [email protected]
                              http://www.talsystems.com

                              Comment


                              • #16
                                A binary file, if small enough to remain in memory, is pretty fast.

                                Comment


                                • #17
                                  Good Architecture

                                  This is a good architecture. Separation of tasks. Separation of display (CGI App which is HTML based) and access to the database (server app) via protocol of your choice (SOAP, RPC, XML, custom, etc..).

                                  This will allow you to use the same server service for different interfaces.
                                  CGI app, FastCGI, IIS ISAPI, custom exe, and any other type of user interface you can think of.

                                  Hope this helps with the other 2%.

                                  Originally posted by Tony Snyder View Post

                                  I'm about 98% convinced that I need to have 2 executables there, a very small CGI, and a separate exe for my main service (much larger), and get them to talk to each other. Then the CGI can start/stop as necessary to support FastCGI, while the rest of the program keeps running the application (dealing with unrelated tasks).

                                  Comment


                                  • #18
                                    This will require lots of upstream to handle 500 persistant connections and the ISP must allow running executables (as was already mentioned.)
                                    It sounds like virtual hosting will be needed, right?
                                    Curious, can you give the 500 people software or must they use a browser? If they are using a browser, connections will be continually opening
                                    even with FastCGI.

                                    http://www.aprelium.com/abyssws/articles/speed.html
                                    http://en.wikipedia.org/wiki/File_sharing
                                    http://support1.cox.com/sdccommon/as...c-8cd5579e132a
                                    Last edited by Mike Doty; 12 Sep 2008, 09:30 PM.

                                    Comment

                                    Working...
                                    X