轉-編寫CGI小結

因爲Carl要用到個人程序,咱們便合做工做。可是他寫的程序是Python的,我寫的程序是Java的,必須得找一種方式進行通訊。儘管有Jython這些東西,可是Carl認爲仍是CGI最簡便。因而,前陣子開始學學CGI怎麼弄。剛開始,以爲好像也不是很難,可是後來進展沒有預期的順利。最後,因爲學院的服務器有CGI模塊可是不容許隨便跑CGI,實驗室服務器又裝的是FastCGI,感受麻煩,最後Carl說仍是用socket吧... - - |||。php

       總體來講,用CGI進行通訊這個計劃算是破產了。雖然是很老舊、基本都不會再用的東西了,可是因爲對我來講是新東西,仍是很好奇,沒有實現,天然是一種可惜。雖然最後沒能用上CGI,可是我的以爲若是學院服務器讓用戶本身跑CGI的話,應該仍是沒問題的。不管怎樣,仍是記錄下一些基本知識,省得之後又忘了。html


       CGI年代久遠,不過卻實現了動態網頁。CGI,準確說,應該是種協議(或者說接口),它使得server中的程序(cgi script)可以經過標準I/O流(STDIN和STDOUT,好比在Java語言裏就是System.in和System.out,在C裏面就是printf等,只要是可以進行標準I/O流讀寫的程序,均可以用來實現CGI)讀取到所需的信息和輸出信息給瀏覽器,而這些所要從客戶端讀取的信息則是包含在某些已經被定義好的環境變量中,咱們只須要讀取這些環境變量,天然就能獲取想要的值了(這也就是CGI這個藉口爲咱們所作的事)。而一般所說的CGI,也有可能泛指CGI程序,即CGI script,是開發者本身所寫的、處理用戶請求的程序。
        整體來講,過程是這樣的:java


        1. 服務器接受到請求
        2. 服務器發現這個請求是須要一個CGI程序來進行處理
        3. 服務器創建一個環境,這個運行環境裏有一些變量,也就是所謂的CGI程序所須要的環境變量
        4. 服務器在這個環境下啓動相應的CGI程序
        5. CGI程序解析本身想要的環境變量來獲取所提交的請求信息
        6. CGI程序對這些請求信息作相應的處理
        7. CGI程序將相應的結果輸出到標準輸出STDOUT,此結果將被輸出到用戶端,呈現給用戶結果。
        8. CGI程序執行完畢,退出程序。linux


       比較詳細來講,原理大概是這樣的:
       1. 客戶端在瀏覽某個網頁的時候,提交表單(form)。而表單的action則指定了要處理該表單的CGI程序,好比: spring

                   <html>
                   <body>
                       <form action="/cgi-bin/plus.cgi" method="GET">
                           <input name="m" size="5">
                           <input name="n" size="5"><br>
                           <input type="submit" values="提交">
                       </form>
                   </body>
                   </html>

        上面的程序中,action="/cgi-bin/plus.cgi" 的意思就是說「這個表單裏的數據,都交給plus.cgi這個程序處理了,而後它處理完這些數據後,再把結果返回給瀏覽器」。
         須要說明的是,plus是一個可執行文件的文件名,好比多是一個shell文件(例如 plus.sh),其後綴不必定是.cgi。那麼爲何要取在這裏取名.cgi呢?緣由是這樣能說明,這個表單處理,是經過一個類型爲cgi的程序進行處理,或者說,經過cgi這種方式讓這個可執行文件對提交的數據進行處理。通常來講,出於安全考慮,不是任何用戶都有權限去寫一個本身的cgi程序而後上傳到服務器、讓該服務器去運行的(好比咱們學院的服務器就不行,哎...)。而只有放在服務器指定目錄(通常爲cgi-bin)下的可執行文件,纔會被被視爲是cgi程序,才能被執行。而通常人是沒法訪問這個目錄的。
        
        2. 而後,name爲「m」和「n」的這兩個變量以及他們的值,就經過某個環境變量輸入到CGI程序中,由CGI程序去進行該CGI程序所指定的處理了。GET和POST獲取「m」和「n」的方式有所不一樣。若是提交方法是GET的話,那麼GET所提交的內容則被包含在名爲QUERY_STRING的環境變量中,當獲得這個環境變量的值後,將其內容解析出來就能夠獲得name/value這樣的值對了,就能夠進行相應的處理了。而POST的話,則須要從標準輸入流STDIN裏面讀取數據,而這些數據到底有多少呢?這個則須要經過讀取CONTENT_LENGTH這個環境變量的值來知道。
        像在C語言裏面,能夠經過getenv函數來直接獲取環境變量的值,好比:getenv("QUERY_STRING"),  getenv("CONTENT_LENGTH")等等。Perl可能要算是寫CGI的最佳語言,可是不會Perl,此處略過。另外,因爲個人程序是用Java寫的,就使得讀取環境變量的方式有點特殊,由於Java是沒有直接獲取這些環境變量的函數的。Java爲什麼不能直接訪問環境變量?簡單說,由於Java內部還有一個屬於System這個類的屬性。所以,咱們一個System.getProperty獲取的是Java中這個System類的屬性的,而不是環境變量的。這些System的屬性也是以name/value這樣的形式來存儲一些Java運行環境的信息的。於是,額外的環境變量(或者說屬性信息)須要用指令java -D的形式,詳見後面的wrapper程序。shell


        經常使用的環境變量有:REQUEST_METHOD,QUERY_STRING,CONTENT_LENGTH,PATH_INFO。其餘的有:SERVER_SOFTWARE,SERVER_NAME,GATEWAY_INTERFACE,SERVER_PROTOCOL,SERVER_PORT,PATH_TRANSLATED,SCRIPT_NAME,REMOTE_HOST,REMOTE_ADDR,AUTH_TYPE,REMOTE_USER,REMOTE_IDENT,CONTENT_TYPE。若是如今忘記這些是幹嗎的了...額...google下吧...
       apache

如今,咱們已經讀取到了所想要的環境變量。可是,這些環境變量的值,是須要咱們進行解析的,由於當初在傳給咱們的時候,就是進行了URL編碼的(URL encode)。好比,若是咱們提交的表單是GET類型的話,再提交完信息後,能夠在地址欄看來相似這樣的url地址:http://www.xxxxxxx.edu/cgi-bin/plus.cgi?m=5&n=6。其中,「m=5&n=6」就是被編碼的字符串,也就是咱們想要獲取的值。而「http://www.xxxxxxx.edu/cgi-bin/plus.cgi」是處理該表單的cgi程序的地址。「?」說明後面的字符串(即「m=5&n=6」)是傳入的參數。不難看出,在編碼的時候,相似於這樣的規則「name1=value1&name2=value2&name3=value3」。此外,非西文的字符串將被「%XX」所代替,空格將被「+」代替。具體地,去參考URL encode的相關資料。
       如何解析這些麻煩的字符串,不須要本身再動手去寫,網上有不少這樣的函數庫,各類語言。直接用網上現成的函數庫來解析就好了。就Java來講,推薦cgi_lib.java這個庫。很方便,應用也很普遍,文件也很小。其中函數的功能是跟cgi_lib.pl同樣的。瀏覽器


       3. 解析字符串後,咱們能夠知道變量m的值爲5,變量n的值爲6。而後就能夠在CGI程序中進行相應的處理了。本身想怎麼處理就怎麼處理。好比,此處是想處理加法,則在本身的CGI程序裏實現m和n的加法便可。安全


       4. 處理完了數據,須要將結果呈現給瀏覽器端的用戶。這個簡單,直接用STDOUT就好了。好比,C語言用printf,Java語言用System.out.println之類的。可是須要注意的是,首先輸出的必須是"Content-type: text/plain"(也就是MIME頭信息,告訴server它隨後的輸出是以純ASCII文本的形式),而後下面空一行(必須空一行),再直接打印出要呈現給用戶的html語句。好比,在Java裏面,就是:服務器

        System.out.println("Content-type: text/plain");
        System.out.println("");

 

        好比,要測驗本身是否有權限能夠寫一個CGI放在服務器上運行,則能夠寫一個最簡單的CGI程序,該程序暫時不處理任何來自用戶的請求,只是輸出"Hello, world"。
        shell程序能夠寫成:

        #!/bin/sh
        echo "Content-type: text/html"
        echo ""
        echo "<html>"
        echo "<body>"
        echo "<h1>Hello, world</h1>"
        echo "</body>"
        echo "</html>"

 

        C語言能夠寫成:

        #include<stdio.h>
        void main(void){
            printf("Content-type: text/html\n");
            printf("\n");
            printf("<html>\n");
            printf("<body>\n");
            printf("<h1>Hello, world</h1>\n");
            printf("</body>");
            printf("/<html>");
        }

        這樣,在客戶端運行就會呈現出<h1>大小的「Hello, world」了。


Java的特別注意:
        1.Java讀取環境變量,只能經過-D的option來加以讀取。
        2.Java生成的.class文件(好比java_plus.class),這不是一個一般意義上的可執行文件,這個文件只是說經過JVM能夠執行起來。而CGI程序是一個直接能夠執行的文件。所以,咱們須要寫一個wrapper,將這個.class文件封裝起來。當調用這個wrapper程序的時候,這個wrapper程序能經過Java指令運行該.class文件。
        結合上訴兩點,則咱們能夠寫一個shell文件當作wrapper程序,以下:

        #!/bin/sh
        java \
        -Dcgi.content_type=$CONTENT_TYPE \
        -Dcgi.content_length=$CONTENT_LENGTH \
        -Dcgi.request_method=$REQUEST_METHOD \
        -Dcgi.query_string=$QUERY_STRING \
        -Dcgi.server_name=$SERVER_NAME \
        -Dcgi.server_port=$SERVER_PORT \
        -Dcgi.script_name=$SCRIPT_NAME \
        -Dcgi.path_info=$PATH_INFO \
        java_plus

        而後將上面的文件保存爲plus.sh,而且放在指定的目錄(好比cgi-bin)便可。這樣,當表單提交新的時候,就會到這個目錄中(由於後綴名爲cgi)去尋找名爲plus的文件,而後執行這個文件。而在java_plus這個文件中,咱們用System.getProperty("cgi.query_string")就能夠訪問到QUERY_STRING這個環境變量了。


推薦一些連接:
http://www.jmarshall.com/easy/cgi/

http://www.eli.sdsu.edu/courses/spring96/cs596/notes/andrew/cgi.html

http://www.javaworld.com/javaworld/jw-01-1997/jw-01-cgiscripts.html

http://apps.hi.baidu.com/share/detail/18814484

http://www.jaguarpc.com/forums/showthread.php?t=2553

http://httpd.apache.org/docs/current/howto/cgi.html

 

至於FastCGI,這個效率比傳統CGI高不少。可是,比較麻煩,須要用循環,還要設置端口什麼的,就沒動手搞那個,只是看了下相關資料。仍是放在這裏吧。

http://www.phpchina.com/download/handbook/linux-html/1272.html

http://www.20cn.net/ns/wz/net/data/20030615005558.htm

http://www.fastcgi.com/devkit/doc/fcgi-java.htm

http://www.citycat.ru/doc/FastCGI/fcdk/index.html

http://hi.baidu.com/coffeefoam/blog/item/1446493be749f3e814cecbb8.html

 

 

轉: https://blog.csdn.net/hungryhuang/article/details/6601684

相關文章
相關標籤/搜索