當前位置:開發者網絡 >> 技術教程 >> CGI教程 >> CGI文檔 >> 內容
精彩推薦
分類最新教程
分類熱點教程
    
動態創建圖像(未定稿2)轉
作者:未知
日期:2003-09-13
人氣:
投稿:Andy.m(轉貼)
來源:未知
字體:
收藏:加入瀏覽器收藏
以下正文:
計數器(Access Counter)可以記錄網頁被訪問的次數,在萬維網上的使用十分普遍,其編寫方法很多,從簡單的SSI命令到用CGI程序生成內嵌圖像等。計數器除了記錄點擊次數外,還可以記錄訪問者的IP、OS、瀏覽器類型等內容,使你對自己網站的訪問情況有個全面的瞭解,本章主要介紹點擊次數的統計和顯示方法。

一、記錄(log)文件
1、grep
    對於Web服務器而言,都有記錄文件記錄著詳細的訪問信息,其名稱通常為access_log,下面是一個例子:


01: dialup-9.austin.io.com - - [02/Oct/1995:20:18:05 -0500] "GET /phoenix/ HTTP/1.0" 200 2330
02: crossnet.org - - [08/Oct/1995:19:56:45 -0500] "HEAD / HTTP/1.0" 200 0
03: dialup-2.austin.io.com - - [09/Oct/1995:07:54:56 -0500] "GET /leading-rein/orders HTTP/1.0" 401 -
04: onramp1-9.onr.com - - [10/Oct/1995:11:11:40 -0500] "GET / HTTP/1.0" 200 1529
05: onramp1-9.onr.com - - [10/Oct/1995:11:11:43 -0500] "GET /accn.jpg HTTP/1.0" 200 20342
06: onramp1-9.onr.com - - [10/Oct/1995:11:11:46 -0500] "GET /home.gif HTTP/1.0" 200 1331
07: dialup-3.austin.io.com - - [12/Oct/1995:08:04:27 -0500] "GET /cgi-bin/env.cgi?
08: SavedName=+&First+Name=Eric&Last+Name=Herrmann&Street=&City=&State=&
09: zip=&Phone+Number=%28999%29+999-9999+&Email+Address=&
10: simple=+Submit+Registration+ HTTP/1.0" 200 1261
11: dialup-20.austin.io.com - - [14/Oct/1995:16:40:04 -0500] "GET /leading-rein/index.cgi?unique_id=9658-199.170.89.58-813706781 HTTP/1.0" 200 1109

    注;當主頁在srm.conf中被命名為welcome.html、index.cgi、index.shtml等時,對其的訪問記錄,可能只含有目錄名而不包含該文件名。
    我們可以用UNIX命令grep來統計主頁被訪問的次數,grep命令通常輸出每一行匹配結果,但可以加上參數-c以輸出匹配行的數目,grep詳見UNIX幫助。下面是一個簡單的例子grep.cgi:


1: #!/usr/local/bin/perl
2: print "content-type: text/html\n\n";
3: $num = `grep -c 'GET / HTTP' /your-server-root/logs/access_log` ;
4: $num += `grep -c 'GET /index.shtml' /your-server-root/logs/access_log` ;
5: $num += `grep -c 'GET /index.html' /your-server-root /logs/access_log` ;
6: print "$num\n";

    現在就可以在主頁中加上SSI指令來顯示計數了,例如:


01: <html>
02: <head><title>grep test</title>
03: <body>
04: <hr noshade>
05: This page has been accessed
06: <!--#exec cgi="grep1.cgi" --> times.
07: <hr noshade>
08: </body>
09: </html>

    別忘了把此文件擴展名改為.shtml。在grep.cgi中,grep命令中包圍模式的單引號告訴UNIX shell不改變該串的內容以精確匹配。
    這種方法有許多缺陷,首先是效率低,用grep來匹配花時間較長,可能要幾秒鐘的時間,這對一個簡單的文本計數器而言太長了。其次,對每一個需要計數器的頁面CGI文件均不相同。最後一個對某些人來說不算是個問題,就是要把Web服務器設置成允許SSI執行,即將其目錄映射略加修改。
2、page-stats
    有一個叫page-stats的程序較好地解決了grep的問題。它查看HTTP daemon的access_log並尋找在標識文件中指定網頁的訪問,然後計算其數目並生成一個HTML形式的統計頁面。這樣,你既得到了頁面的詳細統計信息,同時又得到了可顯示的結果頁面,這樣的例子可在http://www.sci.kun.nl/thalia/page-stats/page-stats_sci.html找到。還可以用grep命令在統計頁面中查找所需信息並生成自己的顯示形式,這樣速度就快多了。
    注意不應在建立自己的統計時運行該程序,否則會導致衝突。應該把它放到任務列表中用UNIX命令cron定時執行,每天、每小時甚至每幾分鐘運行一次。cron詳見UNIX幫助。
3、wusage
    另外一個廣為應用的服務器統計程序是由Thomas Boutell(boutell@boutell.com)編寫的應用於整個服務器的wusage,它生成很詳細的信息,包括服務器怎樣、何時及從何處被訪問等等。它每週運行一次,可以生成漂亮的圖表結果,十分直觀。
    使用wrsage要求使用ncSA或CERN的Web Server或任何有標準記錄文件格式的服務器,還需要有C編譯器,wusage可在www.boutell.com得到。
    隨著時間推移,access_file會越來越龐大,必須定期截留,這時先查看最近一周wusage是否已生成了完整的報表,確定統計結束時間,然後把access_log中該時間前的訪問記錄刪掉,並把wusage生成的結果保存在一個目錄中,以便wusage可以生成過去訪問情況的圖表。

二、創建自己的計數器
    除了使用access_log記錄文件外,我們可以創建自己的計數器。這時首先必須決定用何種形式存貯計數結果,是用文本文件還是用DBM文件,然後要決定是否進行文件同步訪問的保護,這是用文件鎖定來實現的,最後就是確定數據的存貯格式了。
1、使用DBM文件
    對DBM文件而言,常用的函數有dbmopen()、dbmclose()、reset()、each()、values()和keys(),用於計數器時,主要使用前兩個函數。dbmopen()函數把DBM文件與關聯數組綁定,調用語法為:
     dbmopen (%array_name, DB_filename, Read_write_mode);
    如果這時指定的數據庫文件不存在,則自動創建兩個名為DB_filename.dir和DB_filename.pag的文件,除非把讀寫模式設為undef值。
    缺省的,只有64個記錄被讀進內存,可以通過給%array_name分配大小來改變此缺省值。如果你只是給自己的網頁做計數,缺省值已經足夠了,但如果是給整個服務器建立計數器,一般需要更大的值。
    現在看看這三個參數。當調用dbmopen時,%array_name原有的值都被清除(如果有的話),用DBM文件中的值替換掉,給之賦予新值很簡單:$array_name{'new_key'} = value; 當調用dbmclose (%array_name);語句時綁定被解除,關聯數組中的內容被寫如DBM文件,也可以不關閉文件而將內容寫入,方法是調用reset (%array_name);語句,注意此語句並不是重置DBM文件,而是將內存中的數據寫入文件。第二個參數DB_filename是不包含擴展名的,至於讀寫模式詳見本教程的語言部分。
    下面是個使用DBM文件的計數器的簡單例子:


1: dbmopen(%COUNTERS, $DOCUMENT_ROOT/DBM_FILES/counters,0666);
2: if(!(defined($counters{'my_counter'})){
3: $counters{'my_counter'}=0;}
4: $counters{'my_counter'})++;
5: $count=$counters{'my_counter'};
6: dbmclose (counters);

 

2、文本文件
    如果不用DBM文件而用文本文件,除了打開、關閉文件外,還要涉及到數據的讀寫問題,必須確定合適的數據格式,基本步驟如下:


1)打開文件
2)讀取計數
3)自增
4)寫入新值
5)關閉文件

 

3、文件鎖定
    當更新文件內容時,該文件可能同時被另一個進程修改。對計數器程序而言,如果兩個或多個人同時訪問頁面調用了計數器程序,就會出現多個進程同時修改同一文件的情況,這樣有的進程的修改就會失效。當然這並不是太大的問題,只是失去一些計數而已,不過計數器就不準確了,訪問的人越多,這個問題就越大。解決辦法就是修改時通知其它試圖打開該文件的進程等待,或叫文件鎖定,修改完再釋放,允許其它進程打開文件並修改。有兩種方法,一是創建自己的鎖定機制,一種是使用系統函數flock()。
1)創建自己的文件鎖
    這種方法具體實現是創建和刪除一個特定名稱的文件,這在資源共享機制中通常稱作semaphore。下面是個例子:


01: While(-f counter.lock){
02:   select(undef,undef,undef,0.1);}
03: open(LOCKFILE,">counter.lock);
04: dbmopen(%COUNTERS, $DOCUMENT_ROOT/DBM_FILES/counters,0666);
05: if(!(defined($counters{'my_counter'})){
06:   $counters{'my_counter'}=0;}
07: $counters{'my_counter'})++;
08: $count=$counters{'my_counter'};
09: dbmclose (counters);
10: close(LOCKFILE);
11: unlink(counter.lock);

    首先檢查鎖定標誌文件是否存在,如果存在,就說明另一個進程正在使用該文件,於是等待直到該文件(此處命名為counter.lock)不存在為止。此處用select()的特殊形式循環等待,此語句使程序進入休眠狀態一段時間,該時間段由最後一個參數定義。之所以不用sleep()函數是因為其基本單位為秒,對這種文件鎖定而言太長了,幾個微秒就足夠了。
    當鎖定標誌文件不再存在,就創建自己的鎖定標誌文件並開始修改計數,完成後關閉該文件並用unlink函數將之刪除,這樣其它的進程又被允許修改計數。鎖定標誌文件並不是特殊的文件,其文件名也可以由你自己隨意選擇。
2)使用flock()
    其實鎖定文件是很普通的編程步驟,系統函數flock()提供了這一功能,如果在你的系統上不提供的話,可以使用前面介紹的方法自己實現。
    flock()的語法為:
     flock (filehandle, lock_type);
    參數filehandle為用open()函數打開的文件句柄,lock_type可以為下面四個值之一:


1:定義共享鎖。對計數器而言不適用。
2:定義排他鎖。
3:定義非阻止鎖。此處亦不用。
4:解除鎖定。

    使用flock()實現的文件鎖定例子如下:


1a: dbmopen(%counters,"filename", 0666);
or
1b: OPEN(counters,"<filename")'
2: flock(counters,2);
3: if(!(defined($counters{'my_counter'})){
4:   $counters{'my_counter'}=0;}
5: $counters{'my_counter'})++;
6: $count=$counters{'my_counter'};
7: dbmclose (counters);
8: flock(counters,8);

 

4、輸出計數結果
    現在一切就緒,只剩下輸出我們的計數結果了,有三種輸出方法:


1)用上面談到的SSI方法輸出。
2)創建各種文本格式輸出。
3)生成各種漂亮的圖形結果輸出,本教程的《動態創建圖像》一章講述了基本原理並提供了一個x-bitmap格式的小例子,下面介紹兩個更完善和漂亮的程序/庫,這兩個例子均需要C編譯器。

 

5、www Homepage Access Counter
    這是一個廣為應用的網頁計數程序,它利用已有的GIF圖像連接起來生成一個GIF圖像,此程序是用C語言寫的,有適用於各種操作系統的版本,可以在www.fccc.edu/users/muquit/Count.html下載。它提供了很多參數,功能比較齊全,生成的圖像結果也很漂亮,可以選擇圖像格式,其自帶了一些數字樣式,但你可以增加自己的數字圖像生成各種想要的圖像,cervantes.comptons.com/digits/digits.htm提供了很多GIF數字圖像。其參數通過QUERY_STRING傳遞,且必須是小寫字母,下面是個較複雜的調用例子:
     <img src="/cgi-bin/Count.cgi?ft=9|frgb=69;139;50|tr=0|trgb=0;0;0|wxh=15;20|md=6|dd=A|st=5|sh=1|df=count.dat" align=absmiddle>;
    其參數詳細說明和使用方法詳見上述下載網址。如果有必要的話,研究並修改一下其源程序可以使你生成更適合於自己需要的圖像。
6、使用GD圖形庫
    www Homepage Access Counter利用現有的數字圖像簡化了一部分的工作,其目的就是用於圖形計數器。GD圖形庫的功能更加強大,不僅可以用於創建圖形計數器,還可以生成各種統計圖表,還提供了Perl接口庫。GD及其衍生的程序詳見本教程《動態創建圖像》一章。
    在下載的程序中有一個名為gddemo.c的程序演示了其使用方法,在sparke.cs.nyu.edu:8086/cgi.htm有其用於計數器的例子。下面是一個通過GD.pm調用GD圖形庫生成圖像的Perl程序例:


#!/usr/bin/perl

use GD;

# create a new image
$im = new GD:Image(100,100);
# allocate some colors
$white = $im->colorAllocate(255,255,255);
$black = $im->colorAllocate(0,0,0);
$red = $im->colorAllocate(255,0,0);
$blue = $im->colorAllocate(0,0,255);
# make the background transparent and interlaced
$im->transparent($white);
$im->interlaced('true');
# Put a black frame around the picture
$im->rectangle(0,0,99,99,$black);
# Draw a blue oval
$im->arc(50,50,95,75,0,360,$blue);
# And fill it with red
$im->fill(50,50,$red);
# Convert the image to GIF and print it on standard output
print $im->gif;

相關文章: