PerSession工作方式:
客户端创建代理对象(Proxy) 客户端第一次调用代理对象的一个契约操作,代理对象将其调用请求传递给服务宿主 宿主程序创建新的服务对象,并执行请求操作,如果有必要,返回客户端应答 客户端再次发出调用操作的请求,宿主会先判断是否已有建立好的会话,如果存在,则不需要再创建新的服务对象,直接使用老对象即可。 在时间达到指定要求或者因一些特殊原因,会话会过期,此时服务对象销毁。对于会话模式,basicHttpBinding是不支持的,所以如果是发布到iis,终结点的绑定不能是basicHttpBinding,可以选择netTcpBinding和ws2007HttpBinding
下面看看例子:
服务端:
namespace LifeCycleService
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService”。
[ServiceContract(SessionMode= SessionMode.Required)]
public interface ILifeCycleService
{
[OperationContract]
string DoWork();
[OperationContract]
string GetInstance();
}
}
namespace LifeCycleService
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、服务和配置文件中的类名“Service”。
//[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
//[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class LifeCycleServiceImpl : ILifeCycleService
{
// 服务实例的个数
static int instance;
int times = 0;
// 构造函数,初始化callCount,并将服务实例的个数加1
public LifeCycleServiceImpl()
{
instance++;
System.Diagnostics.Debug.WriteLine("Create a new instance: " + instance.ToString() + "");
}
public string GetInstance()
{
string outstr = string.Format("Current Instance is {0}", instance);
return outstr;
}
// 被调用的函数,每次被调用callCount加1
public string DoWork()
{
times++;
string OutStr = string.Format("DoWork() is called by Instance {0}--Times:{1}", OperationContext.Current.SessionId, times);
return OutStr;
}
}
}
<%@ ServiceHost Language="C#" Debug="true" Service="LifeCycleService.LifeCycleServiceImpl" CodeBehind="~/App_Code/LifeCycleService.cs" %>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="LifeCycleService.LifeCycleServiceImpl">
<endpoint address="http://lisheng/LifeCycleService/LifeCycleService.svc" binding="ws2007HttpBinding"
name="LifeCycle_ws2007HttpBinding" contract="LifeCycleService.ILifeCycleService" />
<endpoint address="net.tcp://lisheng/LifeCycleService/LifeCycleService.svc" binding="netTcpBinding"
name="LifeCycle_netTcpBinding" contract="LifeCycleService.ILifeCycleService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
<serviceMetadata httpGetEnabled="true"/>
<!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息-->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false">
<serviceActivations>
<add relativeAddress="LifeCycleService.svc" service="LifeCycleService.LifeCycleServiceImpl" />
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
客户端:
static void Main(string[] args)
{
Console.WriteLine("When the service is ready, press any key to countinue!");
Console.ReadKey(true);
using (LifeCycleServiceClient client1 = new LifeCycleServiceClient("LifeCycle_netTcpBinding"))
{
client1.Open();
Console.WriteLine(string.Format("=============start: {0}================", client1.GetInstance()));
for (int i = 1; i < 4; i++)
{
Console.WriteLine(client1.DoWork());
}
Console.WriteLine(string.Format("=============end: {0}================", client1.GetInstance()));
}
Console.WriteLine();
using (LifeCycleServiceClient client2 = new LifeCycleServiceClient("LifeCycle_ws2007HttpBinding"))
{
client2.Open();
Console.WriteLine(string.Format("=============start: {0}================", client2.GetInstance()));
for (int i = 1; i < 4; i++)
{
Console.WriteLine(client2.DoWork());
}
Console.WriteLine(string.Format("=============end: {0}================", client2.GetInstance()));
}
Console.ReadKey(true);
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="LifeCycle_netTcpBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10"
maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
<ws2007HttpBinding>
<binding name="LifeCycle_ws2007HttpBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</ws2007HttpBinding>
</bindings>
<client>
<endpoint address="http://lisheng/LifeCycleService/LifeCycleService.svc"
binding="ws2007HttpBinding" bindingConfiguration="LifeCycle_ws2007HttpBinding"
contract="LifeCycleService.ILifeCycleService" name="LifeCycle_ws2007HttpBinding">
<identity>
<servicePrincipalName value="host/lisheng" />
</identity>
</endpoint>
<endpoint address="net.tcp://lisheng/LifeCycleService/LifeCycleService.svc"
binding="netTcpBinding" contract="LifeCycleService.ILifeCycleService"
name="LifeCycle_netTcpBinding" />
</client>
</system.serviceModel>
</configuration>
看看另外两种模式工作方式:
PerCall:
- 客户端创建代理对象(Proxy)
- 客户端调用代理对象的一个契约操作,代理对象将其传递给服务宿主程序。
- 宿主应用程序创建一新的服务契约对象,并且执行请求操作
- 在执行完请求操作后,如果要求有应答,那么服务契约会给代理对象一个应答,然后销毁自己(如果实现了IDisposable,则调用Dispose())。
Single :
- 服务端启动,同时创建服务对象
- 客户端通过代理调用契约操作
- 第一步中创建的服务对象接受请求 ,并执行操作,进行必要的应答
- 第一步创建的服务对象将一直保留
- 服务关闭,第一步创建的对象销毁