深入Atlas 系列:客户端网络访问基础结构(上) - WebRequest的工作流程与生命周期

简介:
  ASP.NET AJAX的许多功能会要求异步地访问服务器端,例如访问Web Services,Authentication/Profile Services(事实上和访问Web Services是相同的机制)和Partial Rendering。在ASP.NET AJAX中,所有的这些访问都是通过一个网络访问的基础结构来完成的,无一例外。

  我们话不多说,直接切入正题。先来看一下官方网站上Client Architecture的图示:


   可以在图的左边中间部分可以看到ASP.NET AJAX客户端进行网络访问的基础结构和相关的类。事实上,除了Browser Compatibility Laryer外,WebRequestManager,WebRequest和WebRequestExecutor的子类(在默认情况下则是 XMLHttpExecutor,封装了XMLHttpRequest对象)组成了客户端的Network Communication Layer。无论是Web Services Proxy,还是Role/Authentication/Profile Services都是通过它们访问的。

  一般来说,ASP.NET AJAX提供的类已经足够大多数应用的需求,但是在某些特殊情况,可能需要做一些改变。因此,Network Communication Layer提供了一定程度上的扩展能力——通过提供自定义的WebRequestExecutor子类来替换默认设置:XMLHttpExecutor。 这种改变能够应用于一个单独的WebRequest,也可以对全局进行一个设置。这个我们就能对于客户端的行为做一些简单的修改和补充。这样可以说是 Network Communication Layer唯一的“官方”扩展点,其实能力有限。至于使用一些灵活的办法从JavaScript语言特性能上进行的修改,在这里就忽略不计了。

   这样我们就能对于客户端的行为做一些简单的修改和补充。那么如果对其进行大量的修改会怎么样?如果这种修改的确能够满足您的需要,当然可以。可是这样的 话,Partial Rendering就很可能无法实现了。Partial Rendering的作法是在客户端和服务器端产生一个严谨的协议,用来传递和处理大量的数据。如果有任何改变被加诸于这些数据上,协议就被破坏了,这个 可以说是ASP.NET AJAX的最重要的功能之一的控件也就失效了。

  当然,在自定义WebRequestExecutor时,我 们可以在实现内部检查WebRequest是否正准备进行Partial Rendering的操作,如果是,则将功能委托给XMLHttpExecutor,否则就使用自己的扩展。事实上,ASP.NET AJAX的服务器端为了提供客户端访问Web Services的能力,也是使用了类似的方法扩展ASP.NET 2.0对于Web Services请求的处理(详情请见《 深入Atlas系列:Web Sevices Access in Atlas(2) - 服务器端支持(上) 》。虽然部分内容已经过期,但是其基本原理并没有改变,我会在“深入Atlas系列”的后续文章中进行CTP与RTM之间的比对)。

   我们先来看一幅顺序图,大致了解一下三个对象在工作时的协作方式,再来具体分析一下从一个Request被建立到获得回复的详细过程。另外,对于 Network Communication Layer的扩展点以及其默认实现——WebRequestExecutor和XMLHttpExecutor,我们在下一篇文章里将看一下它们的代码, 以获得开发一个自定义WebRequestExecutor的具体认识。


   上面是从User建立一个WebRequest开始,到得到Response的整个过程(身边只有Visio可用,却不知道怎么画SD,就随便画了一 下,很有问题,但是大家可以先理解它的意思,以后我会重新画的)。这个就是客户端发起异步调用的最常见过程(当然,隐藏了几乎所有的事件,这些事件会在稍 后进行描述)。因此,我想可以通过这幅图来大概了解一下客户端和服务器端是如何交互的。

  接下来,我们详细了解一下这整个流程的每个步骤。

一、创建Sys.Net.WebRequest

   这是发起一个服务器请求的第一步。首先建立一个Sys.Net.WebRequest对象,然后通过addHeader,set_url等方法设置这个 请求的各个信息,然后调用add_complete方法来注册complete事件。请注意,这和CTP版本的Sys.Net.WebRequest不 同。在CTP版本的Sys.Net.WebRequest中,存在着三个事件:complete,timeout和aborted,用户可以有选择地注册 这些事件。 在RTM的Sys.Net.WebRequest中,三个事件被合成了一个complete事件。 不 管这个Request的结果如何,都会在这个触发这个事件,用户需要在响应这个事件的方法里自行根据得到的Response的信息来分辨这个请求的状况。 具体的判断方式稍后再进行说明。在创建完WebRequest对象后,将调用它的invoke方法执行这个请求。一个WebRequest对象只能被 invoke一次。


二、将WebRequest对象交给WebRequestManager执行

   在WebRequest对象的invoke方法被调用以后,它会调用 “Sys.Net.WebRequestManager.executeRequest(this)”将自身交给全局的 WebRequestManager执行。这里的WebRequestManager其实是Sys.Net._WebRequestManager类的实 例。在初始化环境的时候,就会将这个类实例化一个对象,赋值到Sys.Net.WebRequestManager变量中,以一个Singleton的形 象供别的方法调用。它会在处理Request的过程中在特定的时刻触发一些事件,用户可以依靠响应这些事件来改变Request的行为,例如阻止特定的 Request,或者改变Request的一些属性等等。

  乍看下来,RTM版本中的WebRequestManager和CTP中的 WebRequestManager没有很大的区别嘛(引入了几个事件除外)。事实上,个人认为在这个方面Atlas打了自己一个耳光。在CTP版本的 WebRequestManager中,对于管理WebRequest有一套比较复杂的方法,其理由是能够更好地利用好浏览器的资源,以提高 WebRequest的效率。这就是Atlas对外一直声称的“Client Request Stack”,这一点被当作Atlas的重要特点来看待。不过这一点在RTM版本中被取消了,新的WebRequestManager在处理一个 WebRequest对象的时候仅仅是触发事件,然后简单地使用Executor来调用这个WebRequest对象。

  下面列举了调用了executeRequest方法后的关键逻辑:
  1. 检查WebRequest是否指定了WebRequestExecutor(这可以在构造WebRequest的时候指定)。
  2. 如果WebRequest没有指定WebRequestExecutor,则使用set_executor方法分配默认的WebRequestExecutor
  3. 构造Sys.Net.NetworkRequestEventArgs参数对象,触发WebRequestManager的invokingRequest事件。
  4. 如果Sys.Net.NetworkRequestEventArgs对象的cancel属性为true,取消执行Request。
  5. 调用executor对象的executeRequest方法,以执行Request。

三、WebRequestExecutor执行Request

  在这里,以ASP.NET AJAX的默认WebRequestExecutor类:XMLHttpExecutor为例进行说明。在XMLHttpExecutor的 executeRequest方法被调用后,XMLHttpExecutor会构造一个XMLHttpRequest对象,并根据WebRequest的 各项属性设定XMLHttpRequest的对象,并指定XMLHttpRequest对象的onreadystatechange为自身的私有方法 _onReadyStateChange。调用了executeRequest方法后的关键逻辑如下:
  1. 构造XMLHttpRequest对象,并根据WebRequest对象的属性设定它的各项属性。
  2. 使用window.setTimeout用于监听超时发生。
  3. 调用XMLHttpRequest的send方法。
  在timeout的响应方法中调用XMLHttpRequest的abort方法,并调用WebRequest的complete方法。在 _onReadyStateChange方法中清除监听timeout的Timer,并调用complete方法。当然,这只是个简单的描述,事实上还需 要对Executor的属性进行设定。我们将在下篇文章中将对此进行详细讨论。在complete方法被调用后关键逻辑如下:
  1. 触发WebRequestManager的completedRequest事件。
  2. 触发WebRequest的complete事件。

四、用户响应WebRequest的complete事件

  在响应WebRequest的complete事件时,需要对于所获得的结果进行判断,以确定这个Request的结果到底如何,是成功了,还是出错了,亦或是过期了?需要注意的是,我们虽然监听的是WebRequest对象的事件,但是 回调函数的第一个参数是WebRequestExecutor对象 !executor对象在这里事实上应该被看作是一个response。我们就来简单看一下应该如何根据executor对象的属性来判断Request的结果吧。为了对于这部分逻辑有简单而清晰的描述,我就使用代码片断来说明吧。代码框架如下:

function  onComplete(response, eventArgs)
{
    
if  (response.get_aborted())
    {
        
//  Abort
    }
    
else   if  (response.get_responseAvailable())
    {
        
var  statusCode  =  response.get_statusCode();

        
if  (((statusCode  <   200 ||  (statusCode  >=   300 )) )
        {
            
//  Error
        }
        
else
        {
            
//  Success
        }
    }
    
else
    {
        
if  (response.get_timedOut())
        {
            
//  Timeout
        }
        
else
        {
            
//  Error
        }
    }
}

  这就是判断一个Request结果的逻辑框架了,非常清晰。阅读过ASP.NET AJAX客户端代码的朋友们可以发现,在RTM版本中这段逻辑不只一次出现过。我们如果需要直接使用WebRequest对象时,也应该使用这个逻辑进行判断。


   到这里,我们应该已经搞清楚了从一个WebRequest对象被构造出来以后,是如何通过WebRequestManager和 WebRequestExecutor而执行的,之间会触发哪些事件,而最后又是如何通过Response(WebRequestExecutor)对象 来获得Request的结果。在下一篇文章中,我们将通过分析WebRequestExecutor、XMLHttpExecutor以及相关类的实现, 来了解应该如何自定义和使用一个WebRequestExecutor。



本文转自 jeffz 51CTO博客,原文链接:http://blog.51cto.com/jeffz/60690,如需转载请自行联系原作者

相关文章
|
8月前
|
网络协议 Linux 虚拟化
配置VM网络:如何设定静态IP以访问主机IP和互联网
以上就是设定虚拟机网络和静态IP地址的基本步骤。需要注意的是,这些步骤可能会因为虚拟机软件、操作系统以及网络环境的不同而有所差异。在进行设定时,应根据具体情况进行调整。
614 10
|
9月前
|
Shell 开发工具 git
使用代理访问网络各项命令总结
工作中常需设置代理,容易导致环境混乱。本文总结了 SourceTree 无法拉取代码的问题,排查了环境变量、Git 全局配置及系统代理设置,最终通过清除 Git 代理配置解决。内容涵盖排查步骤、命令整理及脚本处理,帮助快速定位并解决代理相关网络问题。
560 3
|
Ubuntu 网络协议 Unix
02理解网络IO:实现服务与客户端通信
网络IO指客户端与服务端通过网络进行数据收发的过程,常见于微信、QQ等应用。本文详解如何用C语言实现一个支持多客户端连接的TCP服务端,涉及socket编程、线程处理及通信流程,并分析“一消息一线程”模式的优缺点。
613 0
|
JSON 中间件 Go
Go 网络编程:HTTP服务与客户端开发
Go 语言的 `net/http` 包功能强大,可快速构建高并发 HTTP 服务。本文从创建简单 HTTP 服务入手,逐步讲解请求与响应对象、URL 参数处理、自定义路由、JSON 接口、静态文件服务、中间件编写及 HTTPS 配置等内容。通过示例代码展示如何使用 `http.HandleFunc`、`http.ServeMux`、`http.Client` 等工具实现常见功能,帮助开发者掌握构建高效 Web 应用的核心技能。
566 61
|
运维 网络协议 Go
Go网络编程:基于TCP的网络服务端与客户端
本文介绍了使用 Go 语言的 `net` 包开发 TCP 网络服务的基础与进阶内容。首先简述了 TCP 协议的基本概念和通信流程,接着详细讲解了服务端与客户端的开发步骤,并提供了简单回显服务的示例代码。同时,文章探讨了服务端并发处理连接的方法,以及粘包/拆包、异常检测、超时控制等进阶技巧。最后通过群聊服务端的实战案例巩固知识点,并总结了 TCP 在高可靠性场景中的优势及 Go 并发模型带来的便利性。
|
域名解析 监控 网络协议
21.7K star!再见吧花生壳,没有公网ip,也能搞定所有网络访问!内网穿透神器NPS
“nps”是一款强大的内网穿透工具,支持多种协议与功能。它无需公网IP或复杂配置,可实现远程桌面、文件共享和私有云搭建等。项目采用Go语言开发,具有高性能与轻量级特点,适用于远程办公、物联网管理等场景。其核心亮点包括零配置穿透、多级代理网络、实时流量监控及企业级安全特性。对比同类工具,“nps”在安装复杂度、协议支持和管理界面方面表现优异。项目地址:https://github.com/ehang-io/nps。
2942 12
|
安全 程序员 Linux
全球头号勒索软件来袭!即刻严控网络访问
全球头号勒索软件来袭!即刻严控网络访问
|
监控 Linux PHP
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
586 20
|
机器学习/深度学习 编解码 TensorFlow
RT-DETR改进策略【模型轻量化】| 替换骨干网络为EfficientNet v1 高效的移动倒置瓶颈结构
RT-DETR改进策略【模型轻量化】| 替换骨干网络为EfficientNet v1 高效的移动倒置瓶颈结构
836 0
RT-DETR改进策略【模型轻量化】| 替换骨干网络为EfficientNet v1 高效的移动倒置瓶颈结构
|
机器学习/深度学习 自动驾驶 计算机视觉
RT-DETR改进策略【模型轻量化】| 替换骨干网络为 GhostNet V1 基于 Ghost Module 和 Ghost Bottlenecks的轻量化网络结构
RT-DETR改进策略【模型轻量化】| 替换骨干网络为 GhostNet V1 基于 Ghost Module 和 Ghost Bottlenecks的轻量化网络结构
750 61
RT-DETR改进策略【模型轻量化】| 替换骨干网络为 GhostNet V1 基于 Ghost Module 和 Ghost Bottlenecks的轻量化网络结构

热门文章

最新文章