本鱼拟成立工作室承接项目开发/软件定制/云设施开发运维/办公设备技术支持等,如您有相关需求,欢迎来询 | ::博客文章推荐::

FSLib.Network网络库使用教程[1] 基本使用

: DOT.NET 木魚 68653℃ 24评论

FSLIB.NETWORK网络库系列文章

  1. 12306订票助手.NET V10.6.1 发布8年前 (2016-09-01)
  2. 开源 FSLIB.NETWORK 库 2.2.0.08年前 (2016-08-02)
  3. FSLIB.NETWORK手册(1) · 基本概念和流程8年前 (2016-05-05)
  4. 原创FSLib.Network库更新 2.0.0 版8年前 (2016-04-05)
  5. 原创FSLib.Network库更新 1.6.0版(目前专注于HTTP的高性能高易用性网络库)9年前 (2015-12-13)
  6. 玩具系列:批量QQ群签到工具v2 (暂时屏蔽自定义位置功能)9年前 (2015-08-29)
  7. 玩具系列:批量QQ群签到工具(支持自定义位置)9年前 (2015-08-28)
  8. 12306订票助手.NET 8.0.8 发布9年前 (2015-08-21)
  9. 12306订票客户端 FOR .NET 演示项目 【7】登录9年前 (2015-08-18)
  10. 12306订票客户端 FOR .NET 演示项目 【6】验证码输入9年前 (2015-08-12)
  11. 12306订票客户端 FOR .NET 演示项目 【5】获得余票数据9年前 (2015-06-10)
  12. 原创FSLib.Network库发布 1.5 版9年前 (2015-06-09)
  13. 12306订票客户端 FOR .NET 演示项目 【4】界面框架&基础数据初始化9年前 (2015-06-08)
  14. 12306订票客户端 FOR .NET 演示项目 【3】流程分析和项目规划9年前 (2015-05-28)
  15. 12306订票客户端 FOR .NET 演示项目 【2】准备工具9年前 (2015-05-22)
  16. 12306订票客户端 FOR .NET 演示项目 【1】项目概况9年前 (2015-05-19)
  17. 原创FSLib.Network库发布 1.4 版9年前 (2015-05-08)
  18. 放一个抓取网页的信息监控小工具源码9年前 (2015-04-27)
  19. FSLib.Network网络库使用教程[2] 实例教程·美女们快到硬盘里来!9年前 (2015-01-30)
  20. FSLib.Network网络库使用教程[1] 基本使用9年前 (2015-01-19)
  21. 原创FSLib.Network库(目前专注于HTTP的高性能高易用性网络库)9年前 (2015-01-18)

上一篇对FSLib.Network库进行了简单的介绍和演示。从本篇开始介绍相关的使用。

1.基本运行机制介绍

FSLib.Network.Http 命名空间下的类是本网络库中用于HTTP处理的相关类型集中存放的地方。由于类库是基于HttpWebRequest以及HttpWebResponse的,所以很多行为表现和逻辑和它们几乎保持一致。

在此基础之上,本类库进行了抽象和总结,并提炼出一整套流程和运行框架。以下分别介绍。

2.相关模型介绍

2.1 HttpClient

HttpClient是开始HTTP处理请求的工厂。它是用来维护、创建、跟踪HTTP请求的一个基本类。可以理解为它是一个容器,维护了所有的Cookies以及全局设置,然后通过它可以创建出不同的HTTP请求实例。

HttpClient的类视图如下。

 fslib_network_lib_tour_basic_class_httpclient

这其中,Create方法是最为重要的方法。它提供了两个重载,用于创建所有的HttpContext上下文。

下面的方法几乎都是用来支撑它的辅助方法。相关的事件也是全局性的事件,也就是说,只要是通过这个HttpClient实例创建出的HttpContext,也会引发这里的事件。一般用于全局性处理。

2.2 IHttpHandler

IHttpHandler是用于创建相关对象(如HttpContextHttpWebRequestHttpWebResponse)的工厂对象,同时也负责一些逻辑性操作(如解析具体地址、解析Cookies等)。

它定义了一个接口,而本类库里已经提供了一个默认实现,大部分情况下够用。如果需要自定义,可以自己完整实现 IHttpHandler接口,或继承默认实现的HttpHandler并改写。

相关类视图如下。

fslib_network_lib_tour_basic_class_httphandler

要使用自己的HttpHandler,在新建HttpClient的时候直接传递新的5对象即可,如下所示。


new HttpClient(new HttpSetting()new HttpHandler());

2.3 HttpSetting

HttpSetting对象为HttpClient所用,用于保存HTTP相关的各项设置。默认情况下,HttpClient有自己默认的HttpSetting实例,一般也够用。如果需要显式设置,可通过在之前章节中类似的方法设置。

HttpSetting类视图如下。

fslib_network_lib_tour_basic_class_httpsetting

 

HttpSetting提供的设置都是默认设置。一些内容(如请求头等)可以在相关的请求中直接改写。

2.4 HttpRequestMessage/HttpResponseMessage

HttpRequestMessage/HttpResponseMessage是将HTTP请求/响应的相关信息(如请求头、请求方式、地址、数据、状态码、标头、ContentType等等)进行封装后的数据类,HttpContext使用它来保存所有和请求或响应相关的内容。

由于这两个类包含成员过多,而且大多都是比较直接的数据存储属性,在此不展示视图。

2.5 HttpRequestContent

当使用POST或PUT等方法发送请求时,往往Request有正文,需要发送一定的数据。而HttpRequestContent即是用来承载实际发送数据的一个数据类。

HttpRequestContent本身是个抽象类,根据实际发送的数据不同,需要使用不同的具象类来执行实际的任务。在本类库中,其相关的类视图如下:

fslib_network_lib_tour_basic_class_httpresponsecontent

 

类库已经内置了大部分用于发送数据的具象类,一般可以直接使用。如果有新增的必要,则可以自定义自己的承载类型。已经内置的操作类如下表所示(加粗行为常用类)。

 类名 名称  说明 
ResponseStringContent 字符串请求内容 和表单数据类似,不过这个类型是将数据内容直接按指定的编码写入请求中。
ResponseJsonContent  JSON内容 和字符串请求内容类似,区别是此类将会设置请求头ContentType为application/json,并将实际对象序列化为字符串再发送。 
ResponseByteBufferContent  字节数组内容 直接将对应的字节数组写入请求中
RequestFormDataContent  表单数据  最常用的类型之一,符合绝大多数网站提交操作的数据类型。包含表单字段以及文件字段,可以发送文件或表单数据。
RequestCopyStreamContent  流复制数据  直接将流中的数据复制到请求流中 
RequestXmlContent  XML内容数据 

和字符串内容类似,区别是此类将对应的ContentType设置为text/xml,并按下列逻辑操作目标对象:

  • 如果数据是字符串,则直接写入
  • 如果数据是XML文档,则取OuterXML后写入
  • 如果以上条件均不符合,则会尝试进行XML序列化后写入 
RequestObjectContent  对象请求数据  最常用的类型之一,和表单数据几乎一致。
区别在于此类可直接接受对象以及匿名对象,底层将会自动根据对象内容取出并初始化底层的表单数据。

2.7 HttpResponseContent

每一个请求都会收到服务器发回的响应,HttpResponseContent即是用来存储实际服务器发来数据并进行转换操作的数据类。

HttpResponseContent本身是个抽象类,只规定了数据接收操作的定义,实际的数据类需要另外实现。本库内置七个常用的数据存储类,相关视图如下。

fslib_network_lib_tour_basic_class_httprequestcontent

如果以上类型均不符合需求,可以另外编写。内置类的详细说明如下表所示(加粗的为常用类)。

类名 说明
ResponseBinaryContent 此类是比较基础的类。此类读取所有服务器发送的数据,并将其最终转换成一个字节数组。
ResponseFileContent  将服务器响应直接保存到指定文件的类 
ResponseStreamContent  将服务器响应分段读取,并允许按照缓冲数组的单位分割处理的类 
ResponseObjectContent  基于BinaryContent,将服务器响应直接转换为对应的实体对象。支持二进制反序列化、JSON反序列化 
ResponseImageContent  基于BinaryContent,将服务器响应直接转换为图片Image对象 
ResponseStringContent  基于BinaryContent,将服务器响应直接读取为一大坨字符串 
ResponseXmlContent  基于StringContent,将结果直接加载为XML文档 

2.8 HttpContext

HttpContext是请求上下文,维护着一个HTTP请求的完整逻辑以及与之相关的数据和状态。它是最终请求的实际执行单元。

请求可以通过Send()SendAsync()SendTask() 来执行,执行的结果不一样,分别是同步执行(阻塞线程)、异步执行(事件通知)以及任务执行。

同时,它负责所有的相关逻辑,如Cookies处理、状态维护、事件通知等。

HttpContext拥有一个强类型的泛型版本 HttpContext<T>,此类型的泛型参数声明了期望的返回结果类型。当服务器返回错误或网络出现错误时,结果可能不能正确返回,此时需要访问 HttpContext.ResponseContent 来获得对应的错误对象。

由于此类型成员过多,在此不做展示。

3.使用模型介绍

这里介绍的是一个通用的创建请求对象的流程。

3.1 创建客户端

直接用new方法创建一个新的客户端。

var client = new HttpClient();

3.2 创建请求上下文

使用 client.Create() 函数创建一个新的HttpContext。

var context = client.Create<string>(HttpMethod.Get, "http://www.baidu.com/");

此函数有大量的参数可供选择,其中绝大部分是可选参数(optional),只有地址(url)和请求方法(method)是必须的。此函数原型如下。

		/// <summary>
		/// 创建网络请求
		/// </summary>
		/// <param name="url">请求地址</param>
		/// <param name="method">方法</param>
		/// <param name="data">写入的数据</param>
		/// <param name="refer">引用页</param>
		/// <param name="saveToFile">保存文件地址</param>
		/// <param name="streamInvoker">流读取对象,仅当返回结果为流时可用</param>
		/// <param name="async">是否是异步发送</param>
		/// <param name="result">预先设置结果类型</param>
		/// <param name="isXhr">是否增加AJAX请求头标记</param>
		/// <param name="contextData">关联的上下文数据</param>
		/// <param name="payloadType">设置当发送对象类型时,设置发送类型。不设置或传递null值将会自动判断</param>
		/// <typeparam name="TResult">结果类型</typeparam>
		/// <returns></returns>
		public HttpContext<TResult> Create<TResult>(
			HttpMethod method,
			string url,
			string refer = null,
			object data = null,
			TResult result = null,
			string saveToFile = null,
			Action<Stream> streamInvoker = null,
			bool async = false,
			bool isXhr = false,
			Dictionary<string, object> contextData = null,
			WebHeaderCollection headers = null,
			RequestPayloadType? payloadType = null,
			bool allowAutoRedirect = false
			) where TResult : class
		{
		}

通过此函数的可选参数,可以直接设置是否是异步发送、是否添加XmlHttpRequest头、上下文数据、引用页、需要定义的请求头等等。

值得一提的是ContextData。每个请求(HttpContext)都附带了一个字典类型的上下文数据(Dictionary<string, object>)用来保存额外的与请求相关的数据。

在此设置的值只是第一步,在之后请求发送之前可以修改。通过此函数创建后,对应的HttpContext状态为未发送,可进行额外的二次设置。设置完成后,通过Send(或相关)方法将其发送出去。 

3.3 发送请求并等待结果

HttpContext发送之后,可以通过Send相关方法发送出去。

Send有三种模式:Send()SendAsync()SendTask(),区别和联系如下。

Send() 直接发送请求。
当启用异步时(Request.Async为true),此方法立刻返回,需要通过事件来对结果进行捕捉。
当未启用异步时,此方法会阻塞线程直到请求结束。
SendAsync() 异步发送请求。
此请求其实等同于设置了Request.AsynctrueSend()方法,但此方法返回的是一个 Deferred<HttpContext> 对象,
此对象类似于Javascript的Promise对象,可以直接使用其方法捕捉结果以及成功与否。
SendTask() 任务模式。
此任务模式将会发送请求并返回一个与之对应的Task对象。
(* 此模式仅在.NET 4.5或更高平台可用)

3.4 错误处理

本类库的原则是摒弃用try...catch来捕捉错误。

当请求完成后,HttpContextIsSuccess 属性来表示当前的请求是否成功(成功的标准是请求状态码<400)。

除此以外,还有 IsValid() 扩展方法用来辅助判断是否成功,此方法除了会判断 IsSuccess属性之外,还会额外判断返回的具体对象是否为空。

如果响应失败,那么可以通过 HttpContext.ResponseContent 获得此时的服务器响应。

注意!当相应失败时,响应的结果类型可能就不是你期望的结果了(此时类库会自动根据响应实际内容判断),因此需要手动判断此刻的响应类型并读取内容。一般来说可以转换为 ResponseBinaryContent 后读取其 StringContent 获得返回的字符串错误信息。

4.扩展

4.1 扩展HttpHandler

默认的HttpHandler提供了IHttpHandler的默认实现,但是可以继承它并扩展。可以进行的操作包含但不局限于装饰相关流、自定义处理HttpWebRequest、自定义处理HttpContext、验证请求等。

4.2 扩展HttpClient

一般来说不需要处理。如果有特异化的需求,可以继承它,并重写相关方法,或添加自己的方法。

4.3 使用事件

使用异步模式时,必须通过相关事件来获得结果。通过事件也可以获得更详细的HTTP请求结果。

4.4 Cookies相关设置

默认情况下,Cookies是自动处理的,策略是全部维护。此默认行为可以修改,可以通过HttpSetting修改全局设置,或通过HttpContextRequest.CookiesHandleMethod来针对请求进行设置。

可设置的范围是:全部忽略;仅发送不接收;默认处理(发送并接收)。

 

 

其它内容请参见 原创FSLib.Network库(目前专注于HTTP的高性能高易用性网络库)

喜欢 (7)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(24)个小伙伴在吐槽
  1. In these days of austerity as well as relative anxiousness about incurring debt, many people balk resistant to the idea of using a credit card in order to make purchase of merchandise or maybe pay for any gift giving occasion, preferring, instead only to rely on the particular tried and trusted procedure for making payment – raw cash. However, if you have the cash on hand to make the purchase in full, then, paradoxically, this is the best time for you to use the cards for several factors.

    Christena Carnall2016-12-25 18:31 回复
  2. I have been surfing online greater than three hours today, yet I by no means found any attention-grabbing article like yours. It is lovely worth enough for me. In my opinion, if all website owners and bloggers made just right content as you probably did, the web will probably be a lot more helpful than ever before.

    Dario Fetter2016-12-25 15:08 回复
  3. 木鱼老大,我需要通过httpclient.create(…);来发送也给post,但是request正文中,有一段请求流。请问应该怎么发送呢?我用的你的最新版库。
    create方法有个参数targetStream。我发送了,但是没有成功。

    trycatch2016-01-21 12:01 回复
    • 有一段请求流?不是很明白。。到这里问吧: http://ask.fishlee.net/category-21

      木魚2016-01-21 12:49 回复
      • 好的,这么快就能得到相应,很辛运~
        这是我发的问题连接:http://ask.fishlee.net/question/53

        trycatch2016-01-21 13:33 回复
  4. 鱼大牛,请问怎么使用webBrowser中的cookies提交请求

    小陈2016-01-08 22:34 回复
  5. 引用已经添加了,为什么还报“未能找到类型或命名空间名称“FSLib”(是否缺少 using 指令或程序集引用?)”

    hbsfgl2015-10-14 12:23 回复
    • 那就是没添加对啊。。

      木魚2015-10-14 18:41 回复
  6. 怎么使用代理ip啊

    Monn2015-05-01 01:36 回复
    • 设置Setting里的Proxy属性。

      木魚2015-05-05 11:33 回复
  7. var client = new HttpClient();
    client.Create(HttpMethod.Post, "https://abc.demo.com/login/check", data: "u=18612513585&p=a123456").Send();
    用这中方法登录,能获得到登录的信息。
    然后client.Create(HttpMethod.Get, "http://abc.demo.com/search").Send();
    却还显示没有登录,是不是登录的cookie还需要怎么传值,传到下面那方法里?

    Demo2015-03-08 17:12 回复
    • Cookies是自动处理的。
      可以抓包调试下。

      木魚2015-03-09 00:49 回复
      • 好的,谢谢您的回答。:-)

        Demo2015-03-09 10:30 回复
  8. private void button1_Click(object sender, EventArgs e)
    {
    //var client = new HttpClient();
    var client = new HttpClient(new HttpSetting(), new HttpHandler());
    var context = client.Create(HttpMethod.Get, "http://www.baidu.com/");
    context.SendAsync();
    bool aa = context.IsSended;
    if (context.IsFinished)
    {
    AppendText(context.Result);
    }
    else
    {
    AppendText("错误!状态码:" + context.Response.Status);
    AppendText("服务器响应:" + context.ResponseContent);
    }
    }
    为什么在执行context.Response.Status的时候总是报:未将对象引用设置到对象的实例。

    小小波2015-01-21 08:01 回复
    • SendAsync() 是异步方法,不会阻塞线程也不会等待请求结束。所以立刻执行后是获得不了相关信息的。

      木魚2015-01-24 03:37 回复
  9. private void button1_Click(object sender, EventArgs e)
    {
    AppendText("正在请求 http://www.baidu.com/ …");

    var client = new HttpClient();
    var context = client.Create(HttpMethod.Get, "http://www.baidu.com/");

    AppendText(context.Result);

    }
    }
    这段代码运行到AppendText(context.Result)处,提示“未将对象引用设置到对象的实例”

    sunny222015-01-20 12:10 回复
    • 通过此函数创建后,对应的HttpContext状态为未发送,可进行额外的二次设置。设置完成后,通过Send(或相关)方法将其发送出去。

      木魚2015-01-20 12:13 回复
      • 成功了,还是我看的不仔细,谢谢大师

        sunny222015-01-20 12:16 回复
  10. 路过

    大大的小蜗牛2015-01-20 11:37 回复
  11. “FSLib.Network.Http.HttpContext”不包含“IsValid”的定义,并且找不到可接受类型为“FSLib.Network.Http.HttpContext”的第一个参数的扩展方法“IsValid”(是否缺少 using 指令或程序集引用?)

    用对象浏览器也没找到这个函数。

    sunny222015-01-20 08:55 回复
    • 这是个扩展方法,需要using FSLib.Network.Http

      木魚2015-01-20 12:06 回复
      • 已经using FSLib.Network.Http 了,还是没有。

        sunny222015-01-20 12:08 回复
    • 嗯。。看了下。目前这个扩展函数的命名空间不正确。需要 using System.Net。后续会改成 FSLib.Network.Http

      木魚2015-01-20 12:38 回复