天天看点

CGI Server Push(CGI Comet) study

Lately we got a requirement about CGI Server Push implementation with plain CGI(aka: CGI Comet) from one of our clients,

I'm not familiar with C, so spent a couple of days making some studies,

And here is what I got so far:

First, CGI Server Push is technically feasible, but  it's quite a departure from standard HTTP usage, which leads to several problems:

    1) There are unfortunate memory implications, because the message keep accumulating, and the browser retains all of that. All messages pile up in memory and on my POC app, Firefox got crashed after it keep running for 40 minutes. (A periodic refresh is a workaround here to solve this problem, say every 10 minutes, we should restart the long lived connection, that will be not pure PUSH, it becomes PUSH + PULL, but at least it works); 

    2) The Two HTTP Connection Limit Issue, I remember this topic has been discussed in our team before, browsers typically only allow 2 concurrent HTTP connections per server. If a browser session has two HTTP connections already, any further connection requests will have to wait until one of these two HTTP connections is finished, but a long lived connection we use to implement PUSH is endless;

    3) The development cycle will be longer if we use CGI Server Push; Since I haven't found a mature opensource framework for CGI PUSH so far, so we need to do a lot of work by ourselves;

If we really need to do that, here are the 2 options we can choose(actually there are also some other solutions for comet, but do not fit our case, so ignored them):

    1) XmlHttpRequest + Message delimited by a special token;

        The solution here is when XHR status is 3(means there is data comes in), then parse the response string and only look at the last valid value, and then invoke a JS method with the value(in JSON, XML or other data object);

    2) Hidden Iframe + Page Streaming with <script> tag;

        Every time browser engine encounter a </script> tag, the script in the tag pair will be excuted, so we can push script to client in denomination of script tag pair;

    Both of the 2 approaches need to restart the long lived connection in a while(I think 5 to 20 minutes is OK) to avoid the increasing memory consuming issue;

Also attach a snippet of a very simple POC on this subject:

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

//amourguo(at)gmail.com

int main()

{

time_t t;

struct tm *p;

//printf("Content-Type:multipart/x-mixed-replace;boundary=amourboundary/r/n/r/n");//for non-IE browsers only

printf("Content-Type:text/plain;");

printf("Cache-Control:no-cache/r/n/r/n");

while(1)

{

t = time(NULL);

p = localtime(&t);

printf("--amourboundarystart");

//printf("Content-Type: text/plain/r/n/r/n");

printf("%d-%d-%d %d:%d:%d",p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec);

printf("--amourboundaryend");

fflush(stdout);

sleep(1000);

}

//printf("--amourboundary--/r/n");

return 0;

P.S.

Since DWR already provide the well-tested mature solution, and we are more fimiliar with that way,

So, if there is any chance, We should not give up talking our client into using DWR, it means LOW risk and agile development for us;

If our client persists in using plain CGI, then we will have a long way to go~

继续阅读