Microsoft .NET 架構提供 網際網路服務的分層的、可擴充的和託管的實現,您可以將這些 網際網路服務快速而輕鬆地整合到您的應用程式中。您的應用程式可建立在可插接式協議的基礎之上以便自動利用新的 網際網路通訊協定 (IP),或者它們可以使用 Windows 通訊端介面的託管實現來使用通訊端層級上的網路。
介紹可插接式協議
Microsoft .NET 架構提供分層的、可擴充的和託管的 網際網路服務實現,您可以將它們快速而輕鬆地整合到您的應用程式中。System.Net 和 System.Net.Sockets 命名空間中的 網際網路存取類可用於實現基於 Web 和基於 Internet 的應用程式。
Internet 應用程式
Internet 應用程式大體上分為兩類:用戶端應用程式(請求資訊)和伺服器應用程式(響應來自用戶端的資訊請求)。典型的 Internet 用戶端-伺服器應用程式是全球資訊網 (World Wide Web),在全球資訊網中,人們使用瀏覽器來訪問世界各地的 Web 服務器上儲存的文檔和其他資料。
應用程式並不限於僅充當其中的一個角色;例如,大家所熟悉的中介層應用程式伺服器通過請求其他伺服器的資料來響應用戶端的請求,在這種情況中,它既作為伺服器,也作為用戶端。
用戶端應用程式通過標識所請求的 Internet 資源以及用於該請求和響應的通訊協議來發出請求。如有必要,用戶端還提供完成請求所需的任何附加資料,例如代理位置或身分識別驗證資訊(使用者名稱、密碼等)。只要構成了請求,就可以將該請求發送到伺服器。
標識資源
.NET 架構使用統一資源識別項 (URI) 來標識所請求的 Internet 資源和通訊協議。URI 至少由三個(也可能是四個)片段組成:方案標識符(標識用於請求和響應的通訊協議)、伺服器標識符(由網域名稱系統 (DNS) 主機名稱或 TCP 地址組成,用於唯一標識 Internet 上的伺服器)、路徑標識符(定位服務器上請求的資訊)以及可選的查詢字串(將資訊從用戶端傳送到伺服器)。例如,URI“http://www.contoso.com/whatsnew.aspx?date=today”就是由方案標識符“http”、伺服器標識符“www.contoso.com”、路徑“whatsnew.aspx”和查詢字串“?date=today”組成的。
只要伺服器接收到請求並進行了響應,它就將該響應返回到用戶端應用程式。響應包括補充資訊,例如內容的類型(如原始文本或 XML 資料)。
.NET 架構中的請求和響應
.NET 架構使用特定類來提供通過請求/響應模型訪問 Internet 所需的三部分資訊:Uri 類(包含您要尋找的 Internet 資源的 URI)、WebRequest 類(包含對該資源的請求)以及 WebResponse 類(為傳入的響應提供容器)。
用戶端應用程式通過將網路資源的 URI 傳遞到 WebRequest.Create 方法來建立
WebRequest 執行個體。此靜態方法建立特定協議(例如 HTTP)的
WebRequest 執行個體。返回的
WebRequest 執行個體提供對屬性的訪問,這些屬性既控制對伺服器的請求,又控制對建立請求時發送的資料流的訪問。
WebRequest 執行個體上的 GetResponse 方法將來自用戶端應用程式的請求發送到在 URI 中標識的伺服器。在響應可能被延遲的情況下,可以使用
WebRequest 執行個體上的 BeginGetResponse 方法非同步建立請求,並且可以使用 EndGetResponse 方法在以後返迴響應。
GetResponse 和
EndGetResponse 方法返回一個
WebResponse 執行個體,該執行個體提供對伺服器返回的資料的訪問。因為此資料由 GetResponseStream 方法作為流提供給發出請求的應用程式,所以它可以在應用程式中的使用資料流的任何地方使用。
WebRequest 類和
WebResponse 類是可插接式協議的基礎——這是一種網路服務的實現,該實現使您可以在開發使用 Internet 資源的應用程式時,無需擔心每一資源使用的協議的特定詳細資料。用
WebRequest 類註冊
WebRequest 的子代類可以管理有關建立與 Internet 資源的實際串連的詳細資料。
舉例來說,HttpWebRequest 類管理有關使用 HTTP 串連到 Internet 資源的詳細資料。預設情況下,當
WebRequest.Create 方法遇到以“http:”或“https:”(HTTP 和安全 HTTP 的協議標識符)開頭的 URI 時,返回的
WebRequest 執行個體可以按照原樣使用,或者可以被類型轉換為
HttpWebRequest 以訪問協議特定的屬性。在大多數情況下,
WebRequest 執行個體提供建立請求所必需的所有資訊。
可被表示為請求/響應事務的所有協議都可以在
WebRequest 中使用。您可以從
WebRequest 和
WebResponse 匯出協議特定的類,然後通過靜態 WebRequest.RegisterPrefix 方法註冊它們以供應用程式使用。
當要求 Internet 請求的用戶端驗證時,
WebRequest 的 Credentials 屬性提供必需的憑據。這些憑據可以是用於基本 HTTP 或簡要身分識別驗證的簡單名稱/密碼對,或者是用於 NTLM 或 Kerberos 身分識別驗證的名稱/密碼/域組。一組憑據可以儲存在 NetworkCredentials 執行個體中,或者多組憑據可以同時儲存在 CredentialCache 執行個體中。
CredentialCache 使用該請求的 URI 和伺服器支援的身分識別驗證方案來確定哪些憑據將發送到伺服器。
通過 WebClient 進行簡單請求
對於需要建立用於 Internet 資源的簡單請求的應用程式而言,WebClient 類提供將資料上傳到 網際網路服務器或從 網際網路服務器下載資料的公用方法。
WebClient 依賴
WebRequest 類來提供對 Internet 資源的訪問;因此,
WebClient 類可以使用任何註冊的可插接式協議。
對於不能使用請求/響應模型的應用程式而言,或者對於需要偵聽網路並發送請求的應用程式而言,
System.Net.Sockets 命名空間提供 TCPClient 類、TCPListener 類和 UDPClient 類。這些類處理使用不同的傳輸協議建立串連的詳細資料,並且作為流嚮應用程式公開網路連接。
對於熟悉 Windows 通訊端介面的開發人員或者需要通過在通訊端層級編程所提供的控制的開發人員,他們將發現
System.Net.Sockets 類可以滿足他們的需要。System.Net.Sockets 類是從託管到 System.Net 類中機器碼的轉換點。在大多數情況下,System.Net.Sockets 類將資料封送到其 Windows 32 位副本中,以及處理任何必需的安全檢查。
請求資料
開發在當今的 Internet 分布式作業環境中啟動並執行應用程式要求採用高效、易用的方法檢索所有類型資源的資料。可插接式協議令您可以開發使用單個介面檢索來自多個 網際網路通訊協定 (IP)的資料的應用程式。
對於簡單請求和響應事務,WebClient 類提供將資料上傳到 網際網路服務器或從 網際網路服務器下載資料的最簡便的方法。
WebClient 提供上傳和下載檔案、發送和接收流以及將資料緩衝區發送到伺服器並接收響應的方法。
WebClient 使用 WebRequest 類和 WebResponse 類來建立與 Internet 資源的實際串連,以便註冊的所有可插接式協議都可供使用。以下樣本請求 Web 頁並在流中返回結果。
[C#]
WebClient myClient = new WebClient();
Stream response = myClient.OpenRead("http://www.contoso.com/index.htm");
// The stream data is used here.
response.Close();
需要進行更複雜的交易處理的用戶端應用程式使用
WebRequest 類及其子代來請求伺服器中的資料。
WebRequest 封裝串連到伺服器、發送請求並接收響應的詳細資料。
WebRequest 是抽象類別,定義可用於使用可插接式協議的所有應用程式的一組屬性和方法。
WebRequest 的子代(例如 HttpWebRequest)實現由
WebRequest 定義的屬性和方法,所採取的方式與基礎協議一致。
WebRequest 類通過使用傳遞到其 Create 方法的 URI 的值來確定要建立的特定衍生類別執行個體,建立
WebRequest 子代的協議特定的執行個體。應用程式通過使用 WebRequest.RegisterPrefix 方法註冊子代的建構函式,指示哪一
WebRequest 子代應被用於處理請求。
通過調用
WebRequest 執行個體上的 GetResponse 方法來建立對 Internet 資源的請求。
GetResponse 方法構造來自於
WebRequest 執行個體的屬性的協議特定的請求,建立與伺服器的 TCP 或 UDP 通訊端串連,並發送該請求。對於將資料發送到伺服器的請求,例如 HTTP
Post 或 FTP
Put 請求,WebRequest.GetRequestStream 方法提供要將資料發送到其中的網路流。
GetResponse 方法返回與
WebRequest 匹配的協議特定
WebResponse,如以下樣本所示。
[C#]
WebRequest req = WebRequest.Create("http://www.contoso.com/");
WebResponse resp = req.GetResponse();
WebResponse 類也是抽象類別,定義可用於使用可插接式協議的所有應用程式的屬性和方法。
WebResponse 子代實現這些用於基礎協議的屬性和方法。例如,HttpWebResponse 類實現用於 HTTP 的
WebResponse 類。
由伺服器返回的資料被提供給由 WebResponse.GetResponseStream 返回的流中的應用程式。您可以像使用任何其他流一樣使用此流,如以下樣本所示。
[C#]
StreamReader sr =
new StreamReader(resp.GetResponseStream(), Encoding.ASCII);
建立 Internet 請求
應用程式通過 WebRequest.Create 方法建立 WebRequest 執行個體。這是建立子代
WebRequest 執行個體的靜態方法(基於傳遞到該執行個體的 URI 方案)。
.NET 架構提供繼承自
WebRequest 的 HttpWebRequest 類,以處理對 Internet 的 HTTP 和 HTTPS 請求。在大多數情況下,
WebRequest 提供您建立請求所需的所有屬性;但是,如有必要,您可以將通過
WebRequest.Create 方法建立的
WebRequest 物件類型轉換為
HttpWebRequest,以訪問請求的 HTTP 特定的屬性。
HttpWebResponse 處理對 Internet 的 HTTP 和 HTTPS 請求的響應。為訪問
HttpWebResponse 的 HTTP 特定屬性,您需要將
WebResponse 類型轉換為
HttpWebResponse。
為處理使用其他 網際網路通訊協定 (IP)(例如 FTP)的請求,您需要匯出
WebRequest 和
WebResponse 的協議特定子代。
使用 Internet 請求和響應類
若要從 Internet 請求資料並讀取響應,請使用以下步驟。
如果要訪問像 Web 頁這樣的資源,請通過用要使用的資源的 URI 調用 WebRequest.Create 來建立 WebRequest 執行個體,如下例所示。
[C#]
WebRequest wReq = WebRequest.Create("http://www.contoso.com/");
注意 .NET 架構為以“http:”、“https:”和“file:”開頭的 URI 提供協議特定的
WebRequest 和
WebResponse 子代。若要訪問其他協議,必須實現協議特定的
WebRequest 和
WebResponse 子代。
在
WebRequest 執行個體中設定任何所需的屬性值。例如,若要支援身分識別驗證,請將 Credentials 屬性設定為 NetworkCredential 類的執行個體,如下例所示。
[C#]
wReq.Credentials =
new NetworkCredential("username","password");
大多數情況下,
WebRequest 執行個體本身就已足夠發送和接收資料。但是,如果需要設定協議特定的屬性,則將
WebRequest 執行個體轉換為協議特定的執行個體。僅當處理
WebRequest 的
WebRequest 子代正確時,此類型轉換才有效。例如,若要訪問 HttpWebRequest 的 HTTP 特定的屬性,請將
WebRequest 轉換為
HttpWebRequest。 下面的代碼執行個體顯示如何設定 HTTP 特定的 UserAgent 屬性。
[C#]
if (wReq is HttpWebRequest)
{
((HttpWebRequest)wReq).UserAgent = ".NET Framework Example Client";
}
若要從 Internet 下載資源,請調用
WebRequest 的 GetResponse 方法。
若要將資料發送或上傳到資源,請調用
WebRequest 的 GetRequestStream 方法,並使用結果 Stream 對象編寫資料。完成上傳後,必須使用 Stream.Close 方法關閉請求流。關閉流後,可以調用
GetResponse 以確保伺服器已正確接收到資料。為 WebResponse 執行個體返回的實際類由所請求的 URI 方案決定。下面的代碼執行個體顯示如何使用
GetResponse 方法建立
WebResponse 執行個體。
[C#]
WebResponse wResp = wReq.GetResponse();
注意 調用
WebResponse 後,必須使用 WebResponse.Close 或
Stream.Close 關閉響應。如果不關閉每個響應,應用程式將用完與伺服器的串連,而無法處理其他請求。
使用
WebResponse 執行個體的 GetResponseStream 方法從網路資源中擷取包含響應資料的流。還可以訪問
WebResponse 執行個體的屬性或將
WebResponse 執行個體轉換為協議特定的執行個體以讀取協議特定的屬性。例如,若要訪問 HttpWebResponse 的 HTTP 特定的屬性,請將
WebResponse 轉換為
HttpWebResponse。下面的程式碼範例顯示如何訪問 HTTP 特定的屬性和讀取響應流。
[C#]
// Read an HTTP-specific property.
if (wResp is HttpWebResponse)
{
DateTime Updated = ((HttpWebResponse)wResp).LastModified;
}
// Get the response stream.
Stream respStream = wResp.GetResponseStream();
// This example uses a StreamReader to read the entire response
// into a string and then writes the string to the console.
StreamReader reader = new StreamReader(respStream, Encoding.ASCII);
String respHTML = reader.ReadToEnd();
Console.WriteLine(respHTML);
// Close the response stream.
respStream.Close();
如果應用程式只需要
WebResponse 中返回的標題資訊並忽略任何返回的資料,則不必擷取響應流。下面的程式碼範例顯示如何從 Internet 主機返回伺服器標題資訊。
[C#]
WebRequest wReq = WebRequest.Create("http://www.contoso.com");
WebResponse wResp = wReq.GetResponse();
string server = wResp.Headers["Server"];
讀取響應中的資料後,必須使用
Stream.Close 方法關閉所有開啟的流或使用
WebResponse.Close 方法關閉響應。
[C#]
wResp.Close();
不必在響應流和
WebResponse 執行個體上都調用
Close 方法,但這樣做並沒有什麼害處。
WebResponse.Close 在關閉響應時調用
Stream.Close。
下面的應用程式範例說明
WebRequest 和
WebResponse 類的用法。
[C#]
using System;
using System.Net;
using System.Text;
using System.IO;
class ClientGet {
public static void Main(string[] args)
{
if (args.Length < 1)
{
showusage();
return;
}
// Get the URI from the command line.
Uri site = new Uri(args[0]);
// Create the request instance.
WebRequest wReq = WebRequest.Create(site);
// Set the HTTP-specific UserAgent property
if (wReq is HttpWebRequest)
{
((HttpWebRequest)wReq).UserAgent =
".NET Framework Example Client";
}
// Get the response instance
WebResponse wResp = wReq.GetResponse();
// Read an HTTP-specific property.
if (wResp is HttpWebResponse)
{
DateTime updated = ((HttpWebResponse)wResp).LastModified;
}
// Get the response stream.
Stream respStream = wResp.GetResponseStream();
// This example uses a StreamReader to read the entire response
// into a string and then writes the string to the console.
StreamReader reader =
new StreamReader(respStream, Encoding.ASCII);
String respHTML = reader.ReadToEnd();
Console.WriteLine(respHTML);
// Close the response and response stream.
wResp.Close();
}
public static void showusage()
{
Console.WriteLine("Attempts to GET a URI.");
Console.WriteLine("\r\nUsage:");
Console.WriteLine(" ClientGet URI");
Console.WriteLine("Example:");
Console.WriteLine(" ClientGet http://www.contoso.com/");
}
}
在網路上使用流
網路資源在 .NET 架構中表示為流。通過對流進行一般處理,.NET 架構提供下列功能:
- 發送和接收 Web 資料的通用方法。無論檔案的實際內容是什麼(HTML、XML 或其他任何內容),應用程式都將使用 Stream.Write 和 Stream.Read 發送和接收資料。
- 整個架構中流的相容性。流用於整個 .NET 架構中,此架構具有豐富的結構來處理流。例如,通過只修改初始化流的幾行代碼,可以修改從 FileStream 中讀取 XML 資料的應用程式,使其改為從 NetworkStream 中讀取資料。NetworkStream 類和其他流之間的主要區別是:NetworkStream 是不可尋找的,CanSeek 屬性始終返回 false,而 Seek 和 Position 方法引發 NotSupportedException。
- 當資料到達時處理資料。流在資料從 Internet 下載的過程中提供對資料的訪問,而不是強制應用程式等待下載完整個資料集。
System.Net.Sockets 命名空間包含一個
NetworkStream 類,該類實現專門用於 Internet 的 Stream 類。System.Net.Sockets 命名空間中的類使用
NetworkStream 類表示流。
若要使用返回的流向網路發送資料,請在 WebRequest 執行個體上調用 GetRequestStream。
WebRequest 將請求標題發送到伺服器,然後您可以通過在返回的流上調用 BeginWrite、EndWrite 或 Write 方法,將資料發送到 Internet 資源。某些協議(如 HTTP)可能要求在發送資料之前設定協議特定的屬性。下面的程式碼範例顯示如何為發送資料設定 HTTP 特定的屬性。該樣本假定變數 sendData 包含要發送的資料,而變數 sendLength 是要發送的資料位元組數。
[C#]
HttpWebRequest request =
(HttpWebRequest) WebRequest.Create("http://www.contoso.com/");
request.Method = "POST";
request.ContentLength = sendLength;
try
{
Stream sendStream = request.GetRequestStream();
sendStream.Write(sendData,0,sendLength);
sendStream.Close();
}
catch
{
// Handle errors . . .
}
若要從網路接收資料,請在 WebResponse 執行個體上調用 GetResponseStream。然後,您可以通過在返回的流上調用 BeginRead、EndRead 或 Read 方法,從 Internet 資源讀取資料。
使用來自網路資源的流時,請記住以下幾點。
- 由於 NetworkStream 類無法更改流中的位置,因此 CanSeek 屬性總是返回 false。Seek 和 Position 方法引發 NotSupportedException。
- 當使用 WebRequest 和 WebResponse 時,通過調用 GetResponseStream 建立的流執行個體是唯讀,通過調用 GetRequestStream 建立的流執行個體是唯寫的。
- 使用 StreamReader 類使編碼更容易。下面的代碼執行個體使用 StreamReader 從 WebResponse 執行個體讀取用 ASCII 編碼的流(此樣本不顯示如何建立請求)。
- 如果網路資源不可用,則對 GetResponse 的調用可能會阻塞。應考慮利用 BeginGetResponse 和 EndGetResponse 方法使用非同步請求。
- 建立對伺服器的串連時,對 GetRequestStream 的調用可能會阻塞。應考慮利用 BeginGetRequestStream 和 EndGetRequestStream 方法對流使用非同步請求。
[C#]
// Create a response object.
WebResponse response = request.GetResponse();
// Get a readable stream from the server.
StreamReader sr =
new StreamReader(response.GetResponseStream(), Encoding.ASCII);
// Use the stream. Remember when you are through with the stream to close
s