WCF服务端运行时架构体系详解[下篇]

作为WCF中一个核心概念,终结点在不同的语境中实际上指代不同的对象。站在服务描述的角度,我们所说的终结点实际上是指ServiceEndpoint对象。如果站在WCF服务端运行时框架来说,终结点实际上指代的是终结点分发器(EndpointDispatcher)。而ServiceEndpoint与EndpointDispatcher是一一匹配的,并且前者是创建后者的基础。而终结点分发器具有自己的运行,即分发运行时(DispatchRuntime)。

目录
一、终结点分发器(EndpointDispatcher)
二、分发运行时(DispatchRuntime)
      可扩展组件            
            认证与授权
            服务实例上下文
            会话关闭通知
            同步上下文
            消息检验
            操作与操作选择
   可扩展属性
           授权
           审核
           事务与会话
           未处理操作
           SOAP ValidateMustUnderstand处理
           并发控制

一、终结点分发器(EndpointDispatcher)

除了之前介绍的三个辅助信道分发器向匹配的终结点分发器实施消息路由的三个属性(AddressFilter、ContractFilter和FilterPriority)之外,你还可以通过属性ContractName和ContractNamespace得到服务契约的名称和命名空间,以通过EndpointAddress属性得到相应的终结点地址。将消息路由到该终结点分发器的信道分发器可以通过属性ChannelDispatcher获得。但是对于终结点分发器来说,其重要的还是通过属性DispatchRuntime表示的分发运行时。

   1: public class EndpointDispatcher
   2: {
   3:     //其他成员
   4:     public string ContractName { get; }
   5:     public string ContractNamespace { get; }
   6:  
   7:     public MessageFilter AddressFilter { get; set; }
   8:     public MessageFilter ContractFilter { get; set; }
   9:     public int FilterPriority { get; set; }
  10:  
  11:     public ChannelDispatcher ChannelDispatcher { get; }
  12:     public DispatchRuntime DispatchRuntime { get; }
  13:     public EndpointAddress EndpointAddress { get; }
  14: }

二、分发运行时(DispatchRuntime)

毫不夸张地说,终结点分发器的分发运行时是WCF整个服务端运行时架构体系的核心,同时也是对WCF服务端服务模型进行扩展重点考虑的对象。分发运行时之所以具有如此重要的地位,原因在于:终结点分发器接收到从信道分发器路由的消息的整个处理是在分发运行时中进行的。

上面分析信道分发器一样,我们首先来看看分发运行时具有哪些可扩展的组件。终结点的分发运行时对应的类型为DispatchRuntime。下面的代码片断列出了这些扩展组件在DispatchRuntime中的对应的属性定义。
   1: public sealed class DispatchRuntime
   2: {
   3:     //其他成员
   4:     public ServiceAuthorizationManager ServiceAuthorizationManager { get; set; }
   5:     public ServiceAuthenticationManager ServiceAuthenticationManager { get; set; }
   6:     public RoleProvider RoleProvider { get; set; }
   7:     public ReadOnlyCollection<IAuthorizationPolicy> ExternalAuthorizationPolicies { get; set; }
   8:  
   9:     public IInstanceContextProvider InstanceContextProvider { get; set; }
  10:     public SynchronizedCollection<IInstanceContextInitializer> InstanceContextInitializers { get; }
  11:     public InstanceContext SingletonInstanceContext { get; set; }
  12:     public IInstanceProvider InstanceProvider { get; set; }
  13:  
  14:     public SynchronizedCollection<IInputSessionShutdown> InputSessionShutdownHandlers { get; }
  15:     public SynchronizationContext SynchronizationContext { get; set; }
  16:  
  17:     public SynchronizedCollection<IDispatchMessageInspector> MessageInspectors { get; }
  18:  
  19:     public SynchronizedKeyedCollection<string, DispatchOperation> Operations { get; }
  20:     public IDispatchOperationSelector OperationSelector { get; set; }
  21: }

1、认证与授权

分发运行时具有一组与安全相关的组件,具体来说是这组组件是与身份认证和授权相关。它们包括用于进行认证的ServiceAuthorizationManager,用于进行授权的ServiceAuthorizationManager,以及在在ASP.NET

Roles安全主体权限模式下实现授权采用的RoleProvider和在自定义安全主体权限模式下自定义的授权策略(通过ExternalAuthorizationPolicies属性表示)。如果你阅读了《深入剖析授权在WCF中的实现[共14篇]》,相对对这四个对象不会感到陌生。

2、服务实例上下文

服务端框架对服务调用请求的处理最终必然体现在服务实例的创建和操作方法的调用。而服务实例并不是单独存储,而是存在于一个上下文中,该上下文被称为实例上下文(InstanceContext)。WCF服务端框架通过一个被称为实例上下文提供者(InstanceContextProvider)来提供基于当前服务请求对应的实例上下文。这里所说的实例上下文的提供机制包括两种情况下:创建新的服务上下文,或者提供一个现有之前创建好的实例上下文。

实例上下文通过类型InstanceContext表示,而所有的实例上下文提供者实现了一个具有如下定义的接口IInstanceContextProvider。WCF为我们提供了相应的实例上下文提供者以实现不同的实例上下文模式:单调(PerCall)、会话(PerSession)和单例(Single)。关于实例上下文、实例上下文模式以及它们最终采用怎样的实例上下文提供者,在《WCF技术剖析(卷1)》第9章《实例管理与会话》有详细的介绍。在这里你需要了解的是:WCF服务端框建最终使用的实例上下文提供者反映在InstanceContextProvider属性上。如果采用单例实例上下文模式,最终提供的实例上下文赋值给了属性SingletonInstanceContext。

   1: public interface IInstanceContextProvider
   2:  {
   3:      InstanceContext GetExistingInstanceContext(Message message, IContextChannel channel);
   4:      void InitializeInstanceContext(InstanceContext instanceContext, Message message, IContextChannel channel);
   5:      bool IsIdle(InstanceContext instanceContext);
   6:      void NotifyIdle(InstanceContextIdleCallback callback, InstanceContext instanceContext);
   7:  }

当实例上下文被创建出来后,如果你需要对其进行一些初始化操作。比如通过检查被创建出来的实例上下文并执行相应的一些操作,或者直接对创建的实例上下文作相应的修改。实例上下文的初始化工作通过一个被称作实例上下文初始化器(InstanceContextInitializer)来实现,它们的类型实现了一个具有如下定义的接口IInstanceContextInitializer。相应的初始化操作定义在Initialize方法中。

   1: public interface IInstanceContextInitializer
   2: {
   3:     void Initialize(InstanceContext instanceContext, Message message);
   4: }

你可以将任意数量的实例上下文初始化器应用到WCF服务端分发系统中,而DispatchRuntime的只读属性InstanceContextInitializers代表了当前的实例上下文初始化器列表。当实例上下文被成功创建后,这些实例上下文初始化器将会以此被执行。

在默认的情况下,WCF会采用反射的方式调用服务类型的无参构造函数来创建服务实例。但是你可以通过自定义一个被称为实例提供者的组件来让WCF服务端分发系统按照你希望的方式创建你想要的实例作为最终的服务实例。所有的InstanceProvider都实现具有如下定义的接口System.ServiceModel.Dispatcher.IInstanceProvider,而DispatchRuntime的InstanceProvider属性表示这个真正被用于提供具体服务实例的实例提供者。《WCF技术剖析(卷1)》第9章《实例管理与会话》中也有关于实例提供者的介绍。

   1: public interface IInstanceProvider
   2:  {
   3:      object GetInstance(InstanceContext instanceContext);
   4:      object GetInstance(InstanceContext instanceContext, Message message);
   5:      void ReleaseInstance(InstanceContext instanceContext, object instance);
   6:  }

3、会话关闭通知

在一个基于双工(Duplex)消息交换模式的会话中,如果客户端在完成了基于当前会话所有消息介绍工作时系统通知服务端以从事一些相关的处理工作,可以通过实现一个被称为输入会话关闭处理器(InputSessionShutdownHandler)的组件。该组件类型实现如下一个名为IInputSessionShutdown的接口。DoneReceiving方法会在接受到上述通知时被调用,而输入参数调用当前的双工信道。如果该信道出现错误(状态变成Faulted),方法ChannelFaulted会被调用。

   1: public interface IInputSessionShutdown
   2: {
   3:     void ChannelFaulted(IDuplexContextChannel channel);
   4:     void DoneReceiving(IDuplexContextChannel channel);
   5: }

和实例上下文初始化器一样,输入会话关闭处理器的数量也没有限制,你可以将多个这样的组件应用到当前分发运行时。而DispatchRumtime的只读属性InputSessionShutdownHandlers代表当前的输入会话关闭处理器列表。

4、同步上下文

在默认的情况下,如果服务寄宿过程中的当前线程具有同步上下文(比如将Windows
Forms应用作为服务的宿主,主线程具有一个类型为WindowsFormsSynchronizationContext的同步上下文),那么后续的处理将在该同步上下文中进行。而你可以通过DispatchRuntime的SynchronizationContext属性得到该同步上下文对象。

这就意味着,所有的处理均是按照同步的方式进行处理的,在高并发的情况下着往往是致命的。我们可以使用在服务类型上应用ServiceBehaviorAttribute特性并通过指定UseSynchronizationContext属性决定是否使用宿主线程当前的同步上下文。

   1: [AttributeUsage(AttributeTargets.Class)]
   2: public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior
   3: {
   4:     //其他成员
   5:     public bool UseSynchronizationContext { get; set; }
   6: }

此外,由于DispatchRuntime的SynchronizationContext属性是可读可写的,如果你为其指定一个特定的同步上下文对象,相应的处理工作也是在该同步上下文中执行。

5、消息检验

WCF允许你对服务端框架进行扩展以实现对路由道终结点分发器的消息进行后续的处理,我们把这个机制成为消息检验。比如说,如果说客户端希望向服务端传输一些与功能无关的上下文信息,可以将其封装成消息报头并添加到请求消息中。你就可以通过这个消息检验机制将上下文信息从相应的消息报头中获取出来。此外,通过消息的检验机制运行你对传入的消息进行相应的更改。如果后续处理中需要相应的控制信息,你可以将其通过该机制将这些信息以消息报头的方式至于传输的消息之中。

消息的检验机制通过自定义消息检验器(MessageInspector)。实际上WCF的客户端和服务端运行时具有自己的消息检验器;客户端的被称为客户端消息检验器(ClientMessageInspector),用于针对发出的请求消息和接收的回复消息进行检验;而服务端的被称为分发消息检验器(DispatchMessageInspector),用于针对于接收的请求消息和发送的回复消息进行检验。在这里我们主要讨论分发消息检验器,在介绍客户端运行时架构的时候我们会对客户端消息检验器进行相应的介绍。

分发消息检验器实现了接口IDispatchMessageInspector。从如下给出的IDispatchMessageInspector接口的定义中我们可以看出,该接口具有两个方法BeforeSendReply和AfterReceiveRequest。从方法名称就可以看出来,它们分别在请求消息被接收后以及回复消息被发送前对消息进行检验。

   1: public interface IDispatchMessageInspector
   2: {
   3:     object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext);
   4:     void BeforeSendReply(ref Message reply, object correlationState);
   5: }

分发运行时具有一个分发消息检验器的列表,该列表通过属性MessageInspectors表示。根据具体应用中针对消息检查的需要,你可以在该列表中添加任意的分发消息检验器,它们按照添加的顺序依次执行。

6、操作与操作选择

我们说了,服务端分发体系对消息请求处理最终体现在多相应操作方法的执行。在服务表示中,操作通过类型OperationDescription表示。当服务端运行时框架通过服务描述被创建的时候,每一个OperationDescription会转变成DiaptchOperation对象。而DispatchRuntime的Operations属性就代表当前终结点的所有DispatchOperation集合。这是一个类似于字典的集合类型,而代表键值的字符串为操作的名称。

由于当前的分发运行时中大都具有多个DispatchOperation对象,而它接收的是一个消息,那么必须具有某种机制以实现根据接收的消息解析出对应的目标操作。这样一种操作的选择机制在WCF分发运行时中是通过一个被称为操作选择器(OperationSelector)的组件来实现的。操作选择器对应的接口为IDispatchOperationSelector,针对消息对操作的选择通过SelectOperation实现,方法的返回值代表操作的名称。当从该方法得到正确的操作名称,WCF就可以从Operations熟悉代表的操作列表中选择正确的DispatchOperation了。

   1: public interface IDispatchOperationSelector
   2: {
   3:     string SelectOperation(ref Message message);
   4: }

至此,我们对分发运行时中基本的可供扩展的组件进行了接收。这些组件是你针对服务端运行时进行扩展的核心。整个分发运行时连同这些可扩展的组件可以通过下图表示。

介绍了分发运行时可供扩展(添加或者替换)的组件之后,我们来看它具有哪些可以修改的属性,通过修改这些属性会对整个消息分发、实例上下文的激活以及服务操作的执行等行为具有怎样的影响。下面的代码片断列出了这些属性。

   1: public sealed class DispatchRuntime
   2: {
   3:     //其他成员
   4:     public PrincipalPermissionMode PrincipalPermissionMode { get; set; }
   5:     public bool ImpersonateCallerForAllOperations { get; set; }
   6:  
   7:     public AuditLogLocation SecurityAuditLogLocation { get; set; }
   8:     public bool SuppressAuditFailure { get; set; }
   9:     public AuditLevel ServiceAuthorizationAuditLevel { get; set; }
  10:     public AuditLevel MessageAuthenticationAuditLevel { get; set; }
  11:  
  12:  
  13:     public bool AutomaticInputSessionShutdown { get; set; }
  14:     public bool ReleaseServiceInstanceOnTransactionComplete { get; set; }
  15:     public bool TransactionAutoCompleteOnSessionClose { get; set; }
  16:     public bool IgnoreTransactionMessageProperty { get; set; }
  17:  
  18:     public DispatchOperation UnhandledDispatchOperation { get; set; }
  19:     public bool ValidateMustUnderstand { get; set; }
  20:     public ConcurrencyMode ConcurrencyMode { get; set; }
  21: }

7、授权

DispatchRuntime的属性PrincipalPermissionMode和ImpersonateCallerForAllOperations是与授权相关的两个属性。前者表示安全主体权限模式,后者表示是否以模拟的客户端Windows帐号执行所有的操作。它们对应于服务行为ServiceAuthorizationBehavior的同名属性。

   1: public sealed class ServiceAuthorizationBehavior : IServiceBehavior
   2: {
   3:     //其他成员
   4:     public bool ImpersonateCallerForAllOperations { get; set; }
   5:     public PrincipalPermissionMode PrincipalPermissionMode { get; set; }
   6: }

8、审核

DispatchRuntime具有四个与审核相关的属性。其中SecurityAuditLogLocation决定了审核日志被入何处;SuppressAuditFailure决定了是否要抑制审核日志记录过程中出现的非关键异常的抛出;而ServiceAuthorizationAuditLevel和MessageAuthenticationAuditLevel则表示具体那些认证和授权相关的事件应该进行审核日志的记录。这四个属性对应于服务行为ServiceSecurityAuditBehavior的同名属性。

   1: public sealed class ServiceSecurityAuditBehavior : IServiceBehavior
   2: {
   3:     //其他成员
   4:     public AuditLogLocation AuditLogLocation { get; set; }
   5:     public bool SuppressAuditFailure { get; set; }
   6:     public AuditLevel MessageAuthenticationAuditLevel { get; set; }
   7:     public AuditLevel ServiceAuthorizationAuditLevel { get; set; }
   8: }

9、事务与会话

接下来介绍四个与会话和事务相关的属性。AutomaticInputSessionShutdown表示服务端是否在客户端关闭输出会话(Output
Session)的时候是否关闭输入会话(Input
Session)。关于会话的相关内容,在《WCF技术剖析(卷1)》第9章《实例管理与会话》中具有详细的介绍。至于这里指的输出和输入则是消息交换模式(MEP:Message
Exchange Pattern),你可以从《WCF技术剖析(卷1)》的第4章《服务契约》中找到关于消息交换模式的详细介绍。

另外两个属性ReleaseServiceInstanceOnTransactionComplete和TransactionAutoCompleteOnSessionClose表示在事务提交之后是否自定释放服务实例,以及在会话关闭之后是否自动提交事务。上述的两个属性分别对应ServiceBehaviorAttribute的同名属性。而AutomaticInputSessionShutdown属性则定于ServiceBehaviorAttribute的AutomaticSessionShutdown属性。

   1: [AttributeUsage(AttributeTargets.Class)]
   2: public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior
   3: {
   4:     //其他成员
   5:     public bool AutomaticSessionShutdown { get; set; }
   6:     public bool ReleaseServiceInstanceOnTransactionComplete { get; set; }
   7:     public bool TransactionAutoCompleteOnSessionClose { get; set; }
   8: }

为了实现基于消息交换的事务传播,事务本身是被封装成一个TransactionMessageProperty对象并被消息属性的形式置于消息之中。而DispatchRuntime的IgnoreTransactionMessageProperty属性表示在接收到这么一消息的时候,是否要忽略其中的TransactionMessageProperty消息属性。

是否忽略消息中的IgnoreTransactionMessageProperty属性决定于终结点的两个要素,即绑定和契约。具体来说,如果绑定不支持事务流转(Transaction

Flow),则该属性返回True。反之,还有需要分析服务契约中应用在操作上的TransactionFlowAttribute设置。相关的逻辑,请参阅本书第3章《事务》。

10、未处理操作

但我们在定义服务契约的时候,通过将OperationContractAttribute特性应用在相应的方法上使其成员一个服务操作。每个操作都具有一个Action属性,并最终决定了针对该操作的请求消息的Action报头的URI。我们可以通过OperationContractAttribute特性的同名属性设定操作的Action。如果该属性没有在OperationContractAttribute特性进行显式设置,对应的操作也具有一个默认值。当ServiceHost被开启之后,每一个终结点对应的操作都转换成DispatchOperation对象,并添加到DispatchRuntime的Operations属性表示的操作列表中。

而实际上我们可以通过OperationContractAttribute将操作的Action定义成“*”。这样的操作被称为为处理操作(Unhandled

Operation)这样的操作最终同样会被转换成DispatchOperation对象,并作为DispatchRuntime的UnhandledDispatchOperation属性而存在。对于请求的消息,不能从DispatchRuntime的Operations属性表示的操作列表中找到一个相匹配的操作时,这个未处理操作会被用于选用。

11、SOAP ValidateMustUnderstand处理

DispatchRuntime的ValidateMustUnderstand属性用于指定是由系统还是由应用程序强制执行 SOAP MustUnderstand标头处理。使用该属性来关闭对到达的消息头强制执行验证。在正常执行过程中,将消息头与UnderstoodHeaders
属性进行比较,来确认是否由服务显式处理到达的消息。将此属性设置为false可以禁用此检查。当设置为false时,应用程序必须检查具有
MustUnderstand="true" 标记的标头,如果其中一个或多个标头没有被理解,则返回错误。当应用程序应接受任何传入的SOAP
消息(例如,使用类型化消息或非类型化消息)以及执行自定义标头处理时,这将很有用。该属性对应于ServiceBehaviorAttribute特性的同名属性。

   1: [AttributeUsage(AttributeTargets.Class)]
   2: public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior
   3: {
   4:     //其他成员
   5:     public bool ValidateMustUnderstand { get; set; }
   6: }



12、并发控制




最后一个属性ConcurrencyMode与并发有关,用于指定三种并发模式(Single、Reentrant和Multiple)中的某一种。它同样对应于ServiceBehaviorAttribute特性的同名属性。

   1: [AttributeUsage(AttributeTargets.Class)]
   2: public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior
   3: {
   4:     //其他成员
   5:     public ConcurrencyMode ConcurrencyMode { get; set; }
   6: }

WCF服务端运行时架构体系详解[上篇]

WCF服务端运行时架构体系详解[中篇]

WCF服务端运行时架构体系详解[下篇]

WCF服务端运行时架构体系详解[续篇]

作者:蒋金楠
微信公众账号:大内老A
微博:www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文链接

时间: 2024-11-02 19:23:55

WCF服务端运行时架构体系详解[下篇]的相关文章

WCF服务端运行时架构体系详解[上篇]

WCF的服务端架构体系又可以成为服务寄宿端架构体系.我们知道,对于一个基于某种类型的服务进行寄宿只需要使用到一个唯一的对象,那就是ServiceHost.甚至在某种语境下,我们所说的服务实际上就是指的对应的ServiceHost对象.整个服务寄宿过程包括两个阶段,即服务描述的创建和服务端运行框架的建立.而第一个阶段创建的服务描述是为了第二个阶段对服务端运行时框架建立服务的,所以我们有必要在对服务描述进行简单的介绍. 目录: 一.从服务描述(Service Description)谈起 二.服务端

WCF服务端运行时架构体系详解[续篇]

终结点分发器在自己的运行时中对请求消息的处理最终肯定体现在相应操作的执行.如果从服务描述的角度来看,操作是一个OperationDescription对象.而服务端分发运行时中的操作则代表的是一个DispatchOperation对象.作为服务描述的一部分,服务所有终结点的所有操作描述(OperationDescription)在ServiceHost创建过程中被创建.而当ServiceHost被正常开始时,这些操作描述最终转换成分发操作(DispatchOperation).而Dispatch

WCF服务端运行时架构体系详解[中篇]

在这篇文章中,我们对信道分发器本身作一个深入的了解,首先来看看它具有哪些可供扩展的组件,以及我们可以针对信道分发器对WCF实现哪些可能的扩展. 目录: ErrorHandler & ServiceThrottle ChannelInitializer IncludeExceptionDetailInFaults ManualAddressing MaxPendingReceives ReceiveSynchronously IsTransactedReceive & MaxTransact

WCF客户端运行时架构体系详解[下篇]

当基于某个终结点创建的ChannelFactory<TChannel>被开启的之后,位于服务模型层的客户端运行时框架被成功构建.站在编程的角度看ChannelFactory<TChannel>,它就是一个创建用于服务调用的服务代理对象的工厂.由于服务调用需要借助于服务代理来完成,我们很有必要从整个客户端运行架构层面来了解服务代理和基于服务代理的服务调用是如何实现的. 目录 一.服务代理是一个透明代理 二.服务调用的流程       操作选择       输入参数检验       序

WCF客户端运行时架构体系详解[上篇]

客户端调用WCF服务的方式不外乎有两种:其一.通过代码生成工具(比如SvcUtil.exe)导入服务的元数据生成服务代理相关的类型:其二.通过ChannelFactory<TChannel>创建服务代理对象.对于前者,生成的服务代理是一个继承自ClientBase<TChannel>的类型.对于这样一个服务代理对象,其内部本质上还是借助于ChannelFactory<TChannel>创建真正用于进行服务调用的代理对象.对于WCF客户端应用编程接口来说,ChannelF

ASP.NET HTTP运行时组成的详解

asp.net|详解 简介 不管使用哪种底层平台,可靠性和性能都是对所有 Web 应用程序的主要要求,尽管从某种意义上讲,这两个要求是相互矛盾的.例如,要构建更可靠.更健壮的应用程序,可能需要将 Web 服务器与具体的应用程序分离,使应用程序在进程外工作.但是,如果在不同于 Web 服务器进程的内存环境中工作,应用程序将变慢.因此,需要采取合理的措施,以确保进程外代码尽可能快地运行. 在构建 Microsoft? ASP.NET 运行时环境时,依据的设计原则即:充分考虑可靠性和性能.得到的 AS

C++:RTTI(RunTime Type Information)运行时类型信息 详解

RTTI, RunTime Type Information, 运行时类型信息, 是多态的主要组成部分, 通过运行时(runtime)确定使用的类型, 执行不同的函数,复用(reuse)接口. dynamic_cast<>可以 使基类指针转换为派生类的指针, 通过判断指针的类型, 可以决定使用的函数. typeid(), 可以判断类型信息, 判断指针指向位置, 在多态中, 可以判断基类还是派生类. 代码: /* * test.cpp * * Created on: 2014.04.22 * A

android与asp.net服务端共享session的方法详解

前言 最近因为工作的需要,要实现一个功能,就是需要通过发送短信进行注册,现在想把短信验证码放到服务器的session值中,当客户端收到短信并提交短信码时由asp.net服务端进行判断,那么如何共享这个session那么需要在android客户端中添加几行代码. 实现方法 如下操作.第一次数据请求时就获取这个cookie的名称并且得到这个cookie的值,这个即是sessionid的值并保存在一个静态变量中,然后在第二次请求数据的时候要将这个sessionid一并放在Cookie中发给服务器,服务

java程序运行时内存分配详解_java

一. 基本概念    每运行一个java程序会产生一个java进程,每个java进程可能包含一个或者多个线程,每一个Java进程对应唯一一个JVM实例,每一个JVM实例唯一对应一个堆,每一个线程有一个自己私有的栈.进程所创建的所有类的实例(也就是对象)或数组(指的是数组的本身,不是引用)都放在堆中,并由该进程所有的线程共享.Java中分配堆内存是自动初始化的,即为一个对象分配内存的时候,会初始化这个对象中变量.虽然Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在栈中分配,也