Examples are given at the end, along with an important note onimplementing server push CGI programs as shell scripts.
Netscape Navigator 1.1 gives content creators and serveradministrators two new open standards-based mechanisms for making thiswork. The mechanisms are similar in nature and effect, butcomplementary. They are:
In server push, the magic is accomplished by using a variant of theMIME message format "multipart/mixed", which lets a single message (orHTTP response) contain many data items. In client pull, the magic isaccomplished by an HTTP response header (or equivalent HTML tag) thattells the client what to do after some specified time delay.
We‘ll explore client pull first...
<META HTTP-EQUIV="Refresh" CONTENT=1><title>Document ONE</title><h1>This is Document ONE!</h1>Here‘s some text. <p>
You will notice that the document reloads itself once a second.
What‘s happening? Simply put, we‘re using the META
tag(a standard HTML 3.0 tag, for simulating HTTP response headers in HTMLdocuments) to tell the browser that it should pretend that the HTTPresponse when "doc1.html" was loaded included the following header:
Refresh: 1
That HTTP header, in turn, tells the browser to go reload (refresh)this document after 1 second has elapsed. If we wanted to wait 12seconds instead, we could have used this HTML directive:
<META HTTP-EQUIV="Refresh" CONTENT=12>
...which is equivalent to this HTTP response header:
Refresh: 12
Note: You should make sure the META
tag is used insidethe HEAD of your HTML document. That means it must appear before anytext or images that would be displayed as part of your document.
So that‘s pretty cool.A couple things to notice:
META
tag or the Refresh
HTTP response header) is given as a part of every retrieval. This is an important point. Each individual "Refresh" directive is one-shot and non-repeating. The directive doesn‘t say "go get this page every 6 seconds from now until infinity"; it says "go get this page in 6 seconds". If you want continuous reloading, you have to give the directive on each retrieval. If you only want the document reloaded once, only give the directive on the first retrieval.
This also means that if you set up an "infinite reload" situation (as the example above does), the only way you can interrupt the infinite reloading is by pressing the "Back" button or otherwise going to a different URL in the current window (or, equivalently, by closing the current window).
Refresh: 12; URL=http://foo.bar/blatz.html
The corresponding META
tag would be:
<META HTTP-EQUIV="Refresh" CONTENT="12; URL=http://foo.bar/blatz.html">
Important note: make sure the URL you give is fully qualified(e.g. http://whatever/whatever). That is, don‘t use a relativeURL.Here are two example documents, "doc2.html" and "doc3.html", each ofwhich causes the other to load (so if you load one of them, yourbrowser will flip back and forth between them indefinitely). Here‘s"doc2.html":
<META HTTP-EQUIV=REFRESH CONTENT="1; URL=http://machine/doc3.html"><title>Document TWO</title><h1>This is Document TWO!</h1>Here‘s some other text. <p>
<META HTTP-EQUIV=REFRESH CONTENT="1; URL=http://machine/doc2.html"><title>Document THREE</title><h1>This is Document THREE!</h1>Here‘s yet more text. <p>
(You should tweak the URLs to match your local system. Remember, theymust be fully specified.)
Now load one of the documents; the browser will load the other in 1second, then the first in another second, then the second again inanother second, and so on forever.
How do you make it stop? The easiest way is to either close thewindow, or put a link in the document(s) that points to somewhereelse. Remember, any retrieval of any document can cause the wholeprocess to stop at any point in time if a fresh directive isn‘t issued-- the process only continues as long as each new document causes itto continue. Thus, the content creator has total control.
Neat trick: the interval can be 0 seconds! This will cause thebrowser to load the new data as soon as it possibly can (after thecurrent data is fully displayed).
Another neat trick: the data that is retrieved can be of anytype: an image, an audio clip, whatever. One fun thing to envision is0-second continuous updating of a live image (e.g. a camera feed), ora series of still images. Poor man‘s animation, kind of. We‘reconsidering mounting a camouflaged IndyCam on the prow of Jim Clark‘sboat and feeding live images to the world using this mechanism.
Yet another neat trick: a "Refresh" header can be returned aspart of any HTTP response, including a redirection. So a single HTTPresponse can say "go get this URL now, and then go get this other URLin 10 seconds".This means you can have a continuous random URL generator! Have anormal random URL generator (such as URouLette)that returns as part of its redirection response a "Refresh" directivethat causes the browser to go get another random URL from the randomURL generator in 18 seconds.
In contrast to client pull, server push takes advantage of aconnection that‘s held open over multiple responses, so the server cansend down more data any time it wants. The obvious major advantage isthat the server has total control over when and how often new data issent down. Also, this method can be more efficient, since new HTTPconnections don‘t have to be opened all the time. The downside isthat the open connection consumes a resource on the server side whileit‘s open (only when the server knows it wants this to happen,though). Also, server push has two other advantages: one is that aserver push is easily interruptible (you can just hit "Stop" andinterrupt the connection), and the other advantage we‘ll talk about alittle later.
First, a short review: the MIME message format is used by HTTP toencapsulate data returned from a server in response to a request.Typically, an HTTP response consists of only a single piece of data.However, MIME has a standard facility for representing many pieces ofdata in a single message (or HTTP response). This facility uses astandard MIME type called "multipart/mixed"; a multipart/mixed messagelooks something like:
Content-type: multipart/mixed;boundary=ThisRandomString--ThisRandomStringContent-type: text/plainData for the first object.--ThisRandomStringContent-type: text/plainData for the second and last object.--ThisRandomString--
The above message contains two data blocks, both of type "text/plain".The final two dashes after the last occurrence of "ThisRandomString"indicate that the message is over; there is no more data.
For server push we use a variant of "multipart/mixed" called"multipart/x-mixed-replace". The "x-" indicates this type isexperimental. The "replace" indicates that each new data block willcause the previous data block to be replaced -- that is, new data willbe displayed instead of (not in addition to) old data.
So here‘s an example of "multipart/x-mixed-replace" in action:
Content-type: multipart/x-mixed-replace;boundary=ThisRandomString--ThisRandomStringContent-type: text/plainData for the first object.--ThisRandomStringContent-type: text/plainData for the second and last object.--ThisRandomString--
The key to the use of this technique is that the server does not pushthe whole "multipart/x-mixed-replace" message down all at once butrather sends down each successive data block whenever it seesfit. The HTTP connection stays open all the time, and the serverpushes down new data blocks as rapidly or as infrequently as it wants,and in between data blocks the browser simply sits and waits for moredata in the current window. The user can even go off and do otherthings in other windows; when the server has more data to send, itjust pushes another data block down the pipe, and the appropriatewindow updates itself.
So here‘s exactly what happens:
#!/bin/shecho "HTTP/1.0 200"echo "Content-type: multipart/x-mixed-replace;boundary=---ThisRandomString---"echo ""echo "---ThisRandomString---"while truedoecho "Content-type: text/html"echo ""echo "<h2>Processes on this machine updated every 5 seconds</h2>"echo "time: "dateecho "<p>"echo "<plaintext>"ps -elecho "---ThisRandomString---"sleep 5done
Note that the boundary is sent to the browser before the sleepstatement. This ensures that the browser will flush its buffers anddisplay all the data that‘s been received up to that point to theuser.
As an example, the following will work:
Content-type: multipart/x-mixed-replace;boundary=ThisRandomStringThe following will not work:
Content-type: multipart/x-mixed-replace; boundary=ThisRandomString
SRC
attribute of theIMG
tag point to an URL for which the server pushes aseries of images.Let‘s stress this point: if you use server push for an individualinlined image, the image will get replaced inside the document eachtime a new image is pushed -- the document itself won‘t get touched(assuming it isn‘t separately subject to server push).
So this is kind of cool -- poor man‘s animation inlined into a staticdocument.
Client pull: generally less efficient, since a new connection must beopened for each new piece of data. However, no connection is heldopen over time.
Note that in real world situations it is common for establishment of anew connection to take a significant amount of time -- i.e., onesecond or more. Given that this is the case, server push willprobably be generally preferable for end-user performance reasons,particularly for information that is frequently updated.
Another consideration is that the server has comparatively morecontrol in the server push situation than in the client pullsituation. One example: there is one distinct open connection foreach instance of server push in use, and the server can elect to (forexample) shut down such a connection at any time (e.g., via a crondaemon) without requiring a whole lot of logic in the server. On theother hand, the same application using client pull will look like manyindependent connections to the server, and the server may need to havea considerable level of complexity in order to manage the situation(e.g., associating client pull requests with particular end users tofigure out who to stop sending new "Refresh" headers to).
An Important Note On Server Push And Shell Scripts: If youwrite a CGI program as a shell script, and the script implements someform of server push where you expect the connection to be open for along time (e.g. an infinitely long stream of images representing livevideo), then the shell script normally will not notice when/if theuser severs the connection on the client side (e.g., by pressing the"Stop" button) and will continue running. This is bad, as serverresources will be thereafter consumed wastefully and uselessly. Theeasiest way to work around this shell script limitation is toimplement such CGI programs using a language like Perl or C -- suchprograms will terminate properly when the user breaks theconnection.
联系客服