我从未在WCF中使用NetNamedPipes,但我花了比我想象的更多的时间学习NetTcp的超时值。我使用以下配置我的NetTcpBindings,并且连接保持活动状态运行得非常好。
服务器 (fú wù qì)
<binding name="MyBindingName" sendTimeout="00:00:30" receiveTimeout="infinite">
<reliableSession enabled="true" inactivityTimeout="00:05:00" ordered="true" />
<security mode="None" />
</binding>
客户:
<binding name="MyBindingName" closeTimeout="00:00:30" openTimeout="00:00:30" receiveTimeout="infinite" sendTimeout="00:00:30">
<reliableSession enabled="true" inactivityTimeout="00:01:00" ordered="true" />
<security mode="None" />
</binding>
我花了最多时间调整的是sendTimeout和receiveTimeout这两个重要的设置。如果你的receiveTimeout相同或小于sendTimeout,那么一旦到达超时时间,通道将会断开。如果receiveTimeout更高且sendTimeout超过阈值,通道将会发出传输级别的keepalive。从我的测试来看,sendTimeout的阈值为30秒。少于这个时间的值不会发送keepalive。
此外,我有一个基于计时器的保持连接调用,我每分钟执行一次,以尝试确保通道正常运行。调用只是返回一个布尔成员:
[OperationContract(IsOneWay = false, IsInitiating = false, IsTerminating = false)]
bool KeepAlive();
public bool KeepAlive()
{
return true;
}
如果在正确的时间获取频道事件,您还可以抓取它们并在出现问题时重新打开连接:
InstanceContext site = new InstanceContext(this);
_proxy = new MyServiceChannel(site);
if (_proxy != null)
{
if (_proxy.Login())
{
//Login was successful
//Add channel event handlers so we can determine if something goes wrong
foreach (IChannel a in site.OutgoingChannels)
{
a.Opened += Channel_Opened;
a.Faulted += Channel_Faulted;
a.Closing += Channel_Closing;
a.Closed += Channel_Closed;
}
}
}
我希望这些对于您在NetNamedPipes方面有一定的翻译和价值。
编辑:捕获服务器重新启动问题的更多选项
当服务器重新启动时,应该导致客户端的通道关闭或出现故障。在客户端端捕获这些事件将使您有使用重新连接计时器直到服务再次可用的选项。
private void Channel_Faulted(object sender, EventArgs e)
{
IChannel channel = sender as IChannel;
if (channel != null)
{
channel.Abort();
channel.Close();
}
//Disable the keep alive timer now that the channel is faulted
_keepAliveTimer.Stop();
//The proxy channel should no longer be used
AbortProxy();
//Enable the try again timer and attempt to reconnect
_reconnectTimer.Start();
}
private void _reconnectTimer_Tick(object sender, System.EventArgs e)
{
if (_proxy == null)
{
InstanceContext site = new InstanceContext(this);
_proxy = new StateManagerClient(site);
}
if (_proxy != null)
{
if (_proxy.Login())
{
//The connection is back up
_reconnectTimer.Stop();
_keepAliveTimer.Start();
}
else
{
//The channel has likely faulted and the proxy should be destroyed
AbortProxy();
}
}
}
public void AbortProxy()
{
if (_proxy != null)
{
_proxy.Abort();
_proxy.Close();
_proxy = null;
}
}
您需要确保重连计时器的登录尝试是在后台线程异步完成的,以便每次尝试登录时不会阻塞用户界面。YMMV