询问者
【WCF】当服务端连接关闭后,但是客户端对象CommunicationState状态仍然是打开状态,为什么?(禁用可靠会话)

问题
全部回复
-
你好,
通道的状态在服务端和客户端是不对称的,这意味着,即使服务端关闭了通道,但是客户端的通道侦听代理依然是开启状态,并且,如果服务端再次开启通道则依然可以正常通信。
请参看下方的官方的文档。
- 已建议为答案 Abraham QianMicrosoft contingent staff 2019年6月24日 8:17
2019年6月24日 8:17 -
你好,
是的,至少在我这边,非双工通信的模式下,在服务端关闭了情况下,重启服务端,客户端仍然可以正常调用服务端的服务。
我这里写一个例子,你可以参看下。
Server(Console application)
class Program { static void Main(string[] args) { using (ServiceHost sh=new ServiceHost(typeof(MyService))) { sh.Open(); Console.WriteLine("serivce is ready...."); Console.ReadLine(); sh.Close(); } } } [ServiceContract] public interface IService { [OperationContract] string SayHello(); } public class MyService : IService { public string SayHello() { return DateTime.Now.ToShortTimeString(); } }
Appconfig(Server).
<system.serviceModel> <services> <service name="VM1.MyService" behaviorConfiguration="mybehavior"> <endpoint address="" binding="basicHttpBinding" contract="VM1.IService"></endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint> <host> <baseAddresses> <add baseAddress="http://localhost:6300/"/> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="mybehavior"> <serviceMetadata/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
Client(Console application,invoke the service by adding service reference).
static void Main(string[] args) { ServiceReference2.ServiceClient client = new ServiceReference2.ServiceClient(); Console.WriteLine(client.SayHello()); Console.WriteLine(client.State); Console.WriteLine("请关闭服务端"); Console.ReadLine(); try { Console.WriteLine(client.SayHello()); } catch (Exception) { Console.WriteLine("调用失败"); } Console.WriteLine("请重启服务端"); Console.ReadLine(); Console.WriteLine(client.SayHello()); Console.ReadLine(); }
客户端Appconfig(auto-generated),需要根据实际情况修改终结点为服务器地址,同一台机器上,Localhost就可以了。
<system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IService1" /> </basicHttpBinding> </bindings> <client> <endpoint address="http://10.157.13.69:6300/" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference2.IService" name="BasicHttpBinding_IService1" /> </client> </system.serviceModel>
Abraham
- 已建议为答案 Abraham QianMicrosoft contingent staff 2019年6月26日 9:49
2019年6月26日 9:49 -
Hi,
所以我并不认为官方文档所述有错,
通道的状态在服务端和客户端是不对称的。
你说的“影响影响下一次业务通信”,在我看来是会话服务,在每次通信的过程中,消息之间具有上下文关系(NetTcpBinding本身也支持会话模式)。如同下方配置
[ServiceContract(SessionMode=SessionMode.Allowed)] Interface IDemo { Public void SayHello(); }
在这种情况下,我们可以显式地控制会话的开始与结束。
[ServiceContract(SessionMode=SessionMode.Required)] interface IService { [OperationContract(IsOneWay=true,IsInitiating =true,IsTerminating =false)] void Start(); [OperationContract(IsInitiating =false,IsTerminating =false)] int Add(int x); [OperationContract(IsOneWay = true,IsInitiating = false,IsTerminating =true)] void End(); }
Abraham
- 已编辑 Abraham QianMicrosoft contingent staff 2019年6月27日 2:09
2019年6月27日 2:07 -
我们用的是percall模式,session会话模式我们不需要,不需要维护状态。
我指的影响下一次通信,指的是链接池中的这个链接对象status还是opened打开状态,但实际上这条长链接已经断了。所以从pool中取出用时就,会出现 An existing connection was forcibly closed by the remote host ,从而影响业务调用。
System.ServiceModel.CommunicationException: The socket connection was aborted.
This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:01:00'. --->
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.ServiceModel.Channels.SocketConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout)2019年6月27日 2:57