程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Web應用程序開發技術

Web應用程序開發技術

編輯:關於C++

Internet無疑是一種重要的信息傳播媒體,隨著其迅猛發展,將會有越來越多的企業、商團、政府機關、學校、科研機構需要在Internet上建立自己的網點。建設一個網點,硬件上需要專用服務器、集線器、路由器,租用數據通信用的專線,軟件上需要安裝網絡操作系統和Internet服務器(www、ftp和gopher服務器),更為重要的是,需要編寫大量的Internet服務器應用程序。這種應用程序接收Internet服務器傳送過來的用戶請求,從內部數據庫檢索出用戶需要的數據,再將數據傳送給用戶。目前在Internet上廣泛應用的是www系統,這種系統用HTML文件格式(即通常所說的網頁)傳播信息,用統一資源定位符(URL)連接世界各地計算機上的信息資源,按照HTTP協議在浏覽器和www服務器之間通信。www服務器又稱為web服務器,相應的服務器應用程序稱為web應用程序。在Windows操作系統下,web應用程序可分為兩種類型:CGI(CommonGateInterface)應用程序和ISAPI(NSAPI)應用程序。這兩種應用程序的功能是一樣的,都是接收web服務器傳送過來的用戶請求,作出響應,將用戶需要的數據以網頁或其它形式傳送給用戶。它們的區別在於,前者用標准輸入輸出或文件在web服務器和web應用程序之間傳送信息,後者則是一種動態聯接庫程序(DLL),其數據可被web服務器直接訪問。ISAPI是指Microsoft的Internet信息服務器(IIS)編程接口,而NSAPI則指Netscape的Internet服務器編程接口。本文將以Borland公司的C++Builder編寫ISAPI(NSAPI)程序的方法為例,介紹開發web應用程序的原理和方法。這種應用程序在32位的Windows操作系統下運行,如果網點使用WindowsNT,則本身就有IIS(包括www、ftp、gopher三個服務器),開發、運行都很方便。

HTTP協議和HTML規范

眾所周知,Internet的底層通信協議是TCP/IP協議,在Internet上傳送的數據被劃分為一個個的IP數據報,每一個IP數據報都指明信源和信宿的地址,沿途的網關按照信宿地址決定數據報的去向。而TCP協議則為通信的雙方建立一條虛電路,保證所有的數據報都能按正確的次序到達目的地。TCP/IP只是實現計算機之間的二進制數據傳輸,對這些數據如何解釋,則是上層協議的事情。開發web應用程序的程序員並不需要過問TCP/IP的工作,我們所必須了解的是其上層協議HTTP。

HTTP是一個應用層協議,目前廣泛應用於web浏覽器和web服務器之間的通信。HTTP用字符串進行通信,所傳送的信息稱為HTTP消息(HTTP-Message)。HTTP消息有兩種類型:浏覽器傳送給服務器的請求消息和服務器傳送給浏覽器的響應消息,其基本格式如下:請求消息:

MethodRequest-URIHTTP-Version;請求行

general-header;通用消息頭

request-header;請求消息頭

entity-header;實體消息頭

;空行

message-body;消息實體

其中三種消息頭的次序是任意的。

響應消息:

HTTP-VersionStatus-CodeReason-Phrase;狀態行

general-header;通用消息頭

response-header;響應消息頭

entity-header;實體消息頭

;空行

message-body;消息實體

其中三種消息頭的次序同樣是任意的。

對於請求消息,請求行是必不可少的,其余部分是可選的。請求行中的Method(方法)指定具體的請求操作,這些方法是HTTP指定的,常用的方法有:

GET浏覽器要求從服務器處獲得信息。

HEAD作用等同於GET但是服務器在響應時不必返回消息實體。通常用來

測試信息資源是否可用,是否已更改。

POST浏覽器向服務器傳送信息。

PUT浏覽器要求將消息中所包含的消息實體寫入服務器。

請求行中的Request-URI是信息資源的定位符,類似於我們通常所說的"網址",但網址通常是指某個網點IP地址對應的域名,而URI則要進一步指明網址下的路徑、網頁文件名、web應用程序名等信息資源。請求行中的HTTP-Version則指明浏覽器所能執行的HTTP協議版本號,多數是1.0或1.1。例如,當我們要求訪問某個abc公司網址www.abc.com上的網頁xyz.htm時,浏覽器將會發出如下請求行:

GEThttp://www.abc.com/xyz.htmHTTP/1.0

請求消息中的通用消息頭、請求消息頭和實體消息頭的一般格式是

field-name:field-value

也就是說,消息頭由多個字段(field)組成,每個字段一行(HTTP用回車換行符CRLF作為每一行的結束標志),每行由字段名和字段值組成,彼此用冒號隔開。HTTP對於每一個字段的意義及其對應的值都有詳細的規定。可供使用的字段很多,但並不是每次發送請求消息都要使用所有的字段,而是根據需要使用其中的若干個。以下是一個請求消息的具體例子:

GET/default.htmHTTP/1.0

Host:http://default

Accept:text/html

User-Agent:Mozilla/2.0

(compatible;NEWTActiveX;Win32)

對於請求消息,常用的字段有:

通用消息頭:Cache-Control、Connection、Date

請求消息頭:Accept、Authorization、

Referer、User-Agent

實體消息頭:Content-Encoding、

Content-Length、Content-Type、Expires

限於篇幅,本文無法詳細解釋每一個字段的含義,有興趣的讀者可參閱參考文獻[1]。

請求消息中的消息實體(Message-Body)是浏覽器要傳送給服務器的數據。使用GET方法的請求消息一般不會有消息實體,而POST和PUT方法則一般會有消息實體,其具體內容可以是任何數據,由實體消息頭中的字段指明其編碼方式、類型和長度。

對於響應消息,開頭的狀態行是必不可少的,其中開頭的HTTP版本號(HTTP-Version)指明服務器所執行的HTTP協議是哪個版本的,然後是由3位數字組成的狀態碼(Status-Code),說明對浏覽器請求消息的響應狀態,最後的原因短語(Reason-Phrase)是對狀態碼的簡短文字說明。

狀態碼的第一位數字定義響應狀態的類型,可能的數值及其含義如下:

1xx:已接收到請求消息,正在處理中。

2xx:對接收到的請求消息已成功地作出響應。

3xx:必須采取進一步的行動才能完成請求。例如,請求消息中的URI對應多個資源,或請求消息要訪問的資源的URI已改變,或必須通過代理服務器才能訪問等。

4xx:浏覽器錯誤,請求消息語法錯誤或請求無法執行。

5xx:服務器錯誤,服務器無法執行一個有效的請求。響應消息的狀態行之後是與請求消息類似的、由各種字段名和字段值組成的消息頭,對於響應消息,常用的字段有:

通用消息頭:Date

響應消息頭:Server、www-Authenticate、Location

實體消息頭:Allow、Content-Encoding、Content-Length、Content-Type、

Expires、Last-Modified

響應消息最後的實體(Message-Body)部分是服務器按照浏覽器的請求傳送回來的數據,最常見的情況就是一個網頁文件的內容。以下是一個響應消息的具體例子,最後一行是消息實體:

HTTP/1.0200OK

Server:Microsoft-PWS-95/2.0

Date:Thu,15Oct199807:40:14GMT

Content-Type:text/html

Content-Length:21

Content:

Hi,gladtomeetyou!

通常,上述消息通信過程是由用戶浏覽某個網頁而發起的。網頁是一個按照HTML規范編寫的純文本文件,其基本框架結構如下:

<HTML>

<HEAD>

<TITLE>網頁標題</TITLE>

</HEAD>

<BODY>

......(網頁的具體內容)

</BODY>

</HTML>

關於HTML規范的詳細內容,可參見參考文獻[2]。其實,我們完全可以通過實驗方法來掌握這個規范。利用一些網頁編輯軟件(例如Microsoft的FrontPage)可以直觀地設計頁面,然後觀察所生成的HTML文本,便可以輕而易舉地學會編寫HTML文件。

在每個網點上都有一個默認網頁,當用戶在浏覽器上指定一個網點的網址時,浏覽器向該網址上的web服務器發出一個請求消息,其中的URI即為該網點web服務器的根目錄。web服務器接收到這個消息後,認為默認網頁就是用戶需要的信息資源並將之傳送給浏覽器。網頁上包含各種鏈接,其基本格式是:

<Ahref="URI">說明文字</A>

當用戶點擊這些鏈接時,就有可能啟動浏覽器與服務器的再次通信。鏈接中的URI可能是同一個網頁中的某個節點,或者是另一個網點的網址,或者是網點上的某一個網頁或其它已存放在網點服務器上的文件。這些都由web服務器自動作出響應,不需要web應用程序的介入。對於編寫web應用程序的程序員,所關心的是一種稱為"查詢"(Query)的鏈接,例如,在網頁中設計如下鏈接:

<Ahref=http://www.Tside.com/Scripts/handll.dll?MyQuery>查詢服務器</A>當用戶點擊這個鏈接時,浏覽器將會向服務器發出類似於如下的請求消息

GET/Scripts/handll.dll?MyQueryHTTP/1.0

Host:http://www.Tside.com網點www.Tside.com上的web服務器接收到這樣的請求消息後,將會向web服務器根目錄下的子目錄Scripts下的web應用程序handll.dll傳送查詢字串"MyQuery",由web應用程序作出響應。通過這種方式,我們可將各種服務功能放置在網頁文件中,用不同的查詢字串表示不同的服務功能,由web應用程序根據查詢字串提供相應的服務。

當需要提供給用戶的服務功能較多時,還可以在上述查詢鏈接的URI中加入路徑(PATH),例如:

http://www.Tside.com/Scripts/handll.dll/MyPath?MyQuery

其中設置的路徑MyPath可以是指服務器磁盤上的子目錄,在上例的情況下,對應的將是服務器根目錄下的子目錄MyPath;也可以是虛擬的路徑,僅供web應用程序作為區分服務功能的分支使用。無論如何,web服務器只是將路徑名傳遞給web應用程序,如何處理完全是應用程序自己的事情。

另外一種重要的編程技術是利用網頁中的表單(Form)。表單用來放置文字輸入框、列表框、組合框、按鈕、選擇框等Windows常見的控件。如同Windows應用程序中的同類控件一樣,這些控件的作用是提供交互操作功能,用戶對於這些控件的操作結果將傳送給web應用程序。如下是一個包含表單的網頁例子,其中的表單包含了一個文字輸入框、一個打勾選擇框和一個按鈕:

<html>

<head><title>FormPageDemo</title></head>

<body>

<formaction="http://default

/scripts/handler.dll"method="POST">

<inputtype="text"name="text1">

<inputtype="checkbox"name="check1">

<inputtype="submit"name="button1"value="Submit">

</form>

</body>

</html>

一個網頁中可以有多個表單,每個表單以

開始,以

結束。其中"action="後面引號內的文字指出接收表單操作結果的web應用程序的URI,"method="後面引號內的文字指出浏覽器向服務器發送該表單操作結果時所使用的方法,一般應該用POST。表單內可以有多個控件,每個控件的格式為

<inputtype="…"name="…"value="…">

其中的type指明控件的類型,對於類型為submit的控件,用戶選中它將使浏覽器發送當前操作的結果。Name是設計者為控件取的名字,value是控件的初始值,可有可無,但對於按鈕,value將是按鈕上的文字。

對於上例,假如我們在文字框中輸入abc,選中選擇框,然後按下類型為submit的按鈕時,浏覽器將用POST方法向網址為http://default的服務器發送請求消息,請求消息中的消息實體將為如下內容:

Text1=abc&Check1=ON&submit=Submit

接收到請求消息的web服務器將把這一串字符傳遞給web應用程序。注意其格式是每個控件對應一個"名值對":控件名=控件值,各個名值對彼此用&聯結起來。Web應用程序可以據此獲知用戶對控件的操作結果。

各種控件的類型名稱及其對應的值可查閱參考文獻[2],或利用網頁編輯器進行實驗,此處不再一一贅述。

用CB開發web應用程序

以下的描述以C++ Builder 6.0為例。

1.選擇菜單File|New,在打開的對話框中選擇圖標WebServerApplication,在再次打開的對話框中選擇ISAPI/NSAPIDynamicLinkLibrary,Delphi將為你建立一個web應用程序的框架,其中包含了一個核心部件TwebModule,負責在web服務器和你的應用程序之間傳送數據。

2.現在我們可以為浏覽器傳送過來的查詢或表單編寫響應代碼。選擇WebModule,在ObjectInspector上將顯示相應的屬性(Properties),選擇其中的屬性Action,按下右端的小按鈕,delphi將打開一個對話框,讓我們設計響應程序段。按下其中的按鈕"Add",Delphi將自動為我們的程序段起一個名字,例如WebActionItem1,並出現在對話框中。這種響應程序段Delphi稱為"動作"(Action),為了區別不同的動作,必須為每一個動作起一個名字,我們可以修改這個名字使之更有意義些。

點擊對話框中的動作名,ObjectInspector將會顯示相應的屬性。其中的MethodType用來指定對何種方法的請求消息作出響應,可供選擇的項目有mtAny、mtGet、mtHead、mtPost和mtPut。其中後四項分別對應請求消息的方法GET、HEAD、POST和PUT,若你想要對所有的方法都作出響應,則可選擇mtAny。

若你的動作是針對查詢請求的,則還可以為屬性PathInfo設置路徑名。例如,假設我們想要對查詢

http://www.Myside.com/Scripts/MyApp.dll/MyPath?MyQuery

作出響應,則可將PathInfo設置為"/MyPath"。注意在上述URI中,www.MySide.com是你的網點的網址,MyApp.dll是你正在編寫的應用程序名稱,你的應用程序將存放在web根目錄下的子目錄Scripts中。

接著是編寫具體代碼。C++ Builder是通過事件響應來執行代碼的,選擇ObjectInspector中的標簽Events,其中只有一個事件OnAction,雙擊右方的編輯框,Delphi將在你的源程序中插入一個空白的過程,例如,

void __fastcall TWebModule1::WebModule1WebActionItem1Action(
    TObject *Sender, TWebRequest *Request, TWebResponse *Response,
    bool &Handled)
{
}

其中最重要的是兩個調用參數Request和Response。Request是一個TWebRequest對象,這種對象具有Accept,Authorization,CacheControl,Connection,...等屬性,這些屬性對應於HTTP請求消息中消息頭的各個字段,這些屬性的值就是這些字段的值。當上述響應過程被調用時,Delphi根據web服務器傳送過來的消息頭及消息實體,設置好對象Request的各個屬性值,然後作為調用參數傳遞給執行動作的過程。對於查詢消息,表示查詢目標的查詢字串(如上面提到的MyQuery)將存放在Request的屬性Query中。如果查詢字串是由"名值對"所構成的,且各名值對之間用&聯結起來,例如

name=dog&color=black

則Delphi還會將各個名值對拆開,再將每一對中的"名"和"值"存放在Request的屬性QueryFields中。QueryFields是Tstrings類型的對象,其屬性Names和Values分別存放各個名值對的"名"和"值"。應用程序通過訪問這些屬性,便可知當前的查詢是什麼。

如果接收到的請求消息是用POST方法傳送表單的操作結果,則如上所述,操作結果將是用&聯結多個名值對的一串字串,這一字串將存放在Request的屬性Content中,並且Delphi將分析這些名值對,將每一對中的"名"和"值"存放在Request的屬性ContentFields中。ContentFields和QueryFields一樣,都是TStrings對象,通過其屬性Names和Values可獲得各個名值對的"名"和"值"。

以上分析使我們知道當前請求消息的詳細情況。無論對請求如何處理,最終我們必須返回一些信息給浏覽器。通常是應用程序將處理結果寫成一個HTML文件,逐行寫入Respons的屬性Content中。也可以利用Delphi的控件PageProducer編寫HTML文件,然後將PageProducer的內容賦值給Response的屬性Content,返回給浏覽器。

Response是TwebResponse類型的對象,其屬性Allow,ContentEncoding,ContentLength,ContentType,Date,Expires,...等對應於響應消息中消息頭的各個字段,應用程序如果需要設置這些字段的值,則可在以上響應過程中設置Response的相應屬性值。

響應過程最後的參數Handled用來說明響應動作是否已完成。

3.一個web應用程序可對多個查詢或表單作出響應,重復步驟2,我們可為各個不同的查詢消息設計不同的響應動作。

以上只是一個概略性的描述,實際編寫起來要繁雜得多。有關細節,可查閱Delphi的幫助文件。

網點總是在運行過程中逐步完善、逐步增加功能的。在開發web應用程序的過程中,應盡量避免在web服務器上調試,以免影響網點的正常運行。我們可以利用一些在單機上就可以運行的個人web服務器(例如Microsoft的PersonalWebServer),在單機上開發web應用程序,調試成功之後再裝入網點服務器。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved