分享
 
 
 

使用.NET访问 Internet(2)

王朝c#·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

实现异步请求

System.Net 类使用 .NET 框架的标准异步编程模型对 Internet 资源进行异步访问。WebRequest 类的 BeginGetResponse 和 EndGetResponse 方法分别启动和完成对 Internet 资源的异步请求。

注意 在异步回调方法中使用同步调用可能会导致严重的性能降低。通过 WebRequest 及其子代实现的 Internet 请求必须使用 Stream.BeginRead 读取由 WebResponse.GetResponseStream 方法返回的流。

下面的 C# 示例程序说明如何通过 WebRequest 类使用异步调用。该示例是一个控制台程序,它从命令行获得 URI,请求此 URI 处的资源,然后在从 Internet 接收数据的过程中在控制台上打印数据。

该程序定义了两个供自己使用的类:一个是 RequestState 类,它在异步调用间传递数据;另一个是 ClientGetAsync 类,它实现对 Internet 资源的异步请求。

RequestState 类在服务于请求的异步方法调用间保留请求的状态。在 RequestState 类中,有包含当前资源请求和收到的响应流的 WebRequest 和 Stream 实例、包含当前从 Internet 资源接收到的数据的缓冲区和包含整个响应的 StringBuilder 实例。当 AsyncCallback 方法向 WebRequest.BeginGetResponse 注册时,RequestState 实例 (ar) 作为 state 参数传递。

ClientGetAsync 类实现对 Internet 资源的异步请求,并将结果响应写到控制台。此类包含以下列表中描述的方法和属性。

allDone 属性包含 ManualResetEvent 类的一个实例,该实例发出信号表示请求已完成。

Main() 方法读取命令行并开始对指定 Internet 资源的请求。此方法创建 WebRequest 实例 wreq 和 RequestState 实例 ar,调用 BeginGetResponse 开始处理请求,然后调用 allDone.WaitOne() 方法,以使应用程序在回调完成后才退出。读取来自 Internet 资源的响应后,Main() 将响应写到控制台,然后应用程序结束。

showusage() 方法将示例命令行写到控制台。如果命令行中没有提供 URI,Main() 将调用此方法。

RespCallBack() 方法为 Internet 请求实现异步回调方法。此方法创建包含来自 Internet 资源的响应的 WebResponse 实例,获取响应流,然后开始从该流中异步读取数据。

ReadCallBack() 方法实现读取响应流的异步回调方法。它将从 Internet 资源接收的数据传输到 RequestState 实例的 ResponseData 属性中,然后对响应流启动另一个异步读取,直到不再有数据返回为止。读取完所有数据后,ReadCallBack() 关闭响应流,并调用 allDone.Set() 方法以指示 ResponseData 中的响应是完整的。

注意 关闭所有网络流至关重要。如果没有将所有的请求和响应流都关闭,应用程序将用完服务器连接,而无法处理其他请求。

[C#]

using System;

using System.Net;

using System.Threading;

using System.Text;

using System.IO;

// The RequestState class passes data across async calls.

public class RequestState

{

const int BufferSize = 1024;

public StringBuilder RequestData;

public byte[] BufferRead;

public WebRequest Request;

public Stream ResponseStream;

// Create Decoder for appropriate enconding type.

public Decoder StreamDecode = Encoding.UTF8.GetDecoder();

public RequestState()

{

BufferRead = new byte[BufferSize];

RequestData = new StringBuilder(String.Empty);

Request = null;

ResponseStream = null;

}

}

// ClientGetAsync issues the async request.

class ClientGetAsync

{

public static ManualResetEvent allDone = new ManualResetEvent(false);

const int BUFFER_SIZE = 1024;

public static void Main(string[] args)

{

if (args.Length < 1)

{

showusage();

return;

}

// Get the URI from the command line.

Uri httpSite = new Uri(args[0]);

// Create the request object.

WebRequest wreq = WebRequest.Create(httpSite);

// Create the state object.

RequestState rs = new RequestState();

// Put the request into the state object so it can be passed around.

rs.Request = wreq;

// Issue the async request.

IAsyncResult r = (IAsyncResult) wreq.BeginGetResponse(

new AsyncCallback(RespCallback), rs);

// Wait until the ManualResetEvent is set so that the application

// does not exit until after the callback is called.

allDone.WaitOne();

Console.WriteLine(rs.RequestData.ToString());

}

public static void showusage() {

Console.WriteLine("Attempts to GET a URL");

Console.WriteLine("\r\nUsage:");

Console.WriteLine(" ClientGetAsync URL");

Console.WriteLine(" Example:");

Console.WriteLine(" ClientGetAsync http://www.contoso.com/");

}

private static void RespCallback(IAsyncResult ar)

{

// Get the RequestState object from the async result.

RequestState rs = (RequestState) ar.AsyncState;

// Get the WebRequest from RequestState.

WebRequest req = rs.Request;

// Call EndGetResponse, which produces the WebResponse object

// that came from the request issued above.

WebResponse resp = req.EndGetResponse(ar);

// Start reading data from the response stream.

Stream ResponseStream = resp.GetResponseStream();

// Store the response stream in RequestState to read

// the stream asynchronously.

rs.ResponseStream = ResponseStream;

// Pass rs.BufferRead to BeginRead. Read data into rs.BufferRead

IAsyncResult iarRead = ResponseStream.BeginRead(rs.BufferRead, 0,

BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);

}

private static void ReadCallBack(IAsyncResult asyncResult)

{

// Get the RequestState object from AsyncResult.

RequestState rs = (RequestState)asyncResult.AsyncState;

// Retrieve the ResponseStream that was set in RespCallback.

Stream responseStream = rs.ResponseStream;

// Read rs.BufferRead to verify that it contains data.

int read = responseStream.EndRead( asyncResult );

if (read > 0)

{

// Prepare a Char array buffer for converting to Unicode.

Char[] charBuffer = new Char[BUFFER_SIZE];

// Convert byte stream to Char array and then to String.

// len contains the number of characters converted to Unicode.

int len =

rs.StreamDecode.GetChars(rs.BufferRead, 0, BUFFER_SIZE, charBuffer, 0);

String str = new String(charBuffer, 0, len);

// Append the recently read data to the RequestData stringbuilder

// object contained in RequestState.

rs.RequestData.Append(

Encoding.ASCII.GetString(rs.BufferRead, 0, read));

// Continue reading data until

// responseStream.EndRead returns –1.

IAsyncResult ar = responseStream.BeginRead(

rs.BufferRead, 0, BUFFER_SIZE,

new AsyncCallback(ReadCallBack), rs);

}

else

{

if(rs.RequestData.Length>0)

{

// Display data to the console.

string strContent;

strContent = rs.RequestData.ToString();

}

// Close down the response stream.

responseStream.Close();

// Set the ManualResetEvent so the main thread can exit.

allDone.Set();

}

return;

}

}

使用应用程序协议

.NET 框架支持 Internet 上通用的应用程序协议。本节内容包括关于在 .NET 框架中使用 HTTP、TCP 和 UDP 支持的信息,和关于使用 Windows 套接字接口实现自定义协议的信息。

HTTP

.NET 框架使用 HttpWebRequest 和 HttpWebResponse 类来提供对 HTTP 协议的全面支持,而 HTTP 协议构成了大部分的 Internet 通信量。每当静态方法 WebRequest.Create 遇到以“http”或“https”开头的 URI 时,在默认情况下将返回这些从 WebRequest 和 WebResponse 派生的类。多数情况下,WebRequest 和 WebResponse 类提供生成请求所需的一切,但如果需要访问作为属性公开的 HTTP 特定功能,则可以将这些类的类型转换为 HttpWebRequest 或 HttpWebResponse。

HttpWebRequest 和 HttpWebResponse 封装“标准 HTTP 请求和响应”事务,并提供对通用 HTTP 标头的访问。这些类还支持大部分的 HTTP 1.1 功能,其中包括管线、块区、身份验证、预身份验证、加密、代理支持、服务器证书验证以及连接管理。自定义标头和不是通过属性提供的标头可存储在 Headers 属性中并可通过此属性访问。

以下示例显示如何访问 HTTP 特定的属性,在本例中为关闭 HTTP Keep-alive 行为并从 Web 服务器获取协议版本号。

[C#]

HttpWebRequest HttpWReq =

(HttpWebRequest)WebRequest.Create("http://www.contoso.com");

// Turn off connection keep-alives.

HttpWReq.KeepAlive = false;

HttpWebResponse HttpWResp = (HttpWebResponse)HttpWReq.GetResponse();

// Get the HTTP protocol version number returned by the server.

String ver = HttpWResp.ProtocolVersion.ToString();

HttpWResp.Close();

HttpWebRequest 是 WebRequest 使用的默认类,不需要注册它就可以将 URI 传递给 WebRequest.Create 方法。

可以通过将 AllowAutoRedirect 属性设置为 true(默认值)使应用程序自动遵循 HTTP 重定向。应用程序将重定向请求,而 HttpWebResponse 的 ResponseURI 属性则将包含响应请求的实际 Web 资源。如果将 AllowAutoRedirect 设置为 false,则应用程序必须能够将重定向作为 HTTP 协议错误处理。

应用程序通过捕捉 Status 设置为 WebExceptionStatus.ProtocolError 的 WebException 来接收 HTTP 协议错误。Response 属性包含由服务器发送的WebResponse,并指示遇到的实际 HTTP 错误。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有