wcf的客户端意外退出,服务器崩溃
我用wcf写了一个聊天室,用的tcp协议连接的, 现在是如果有一个客户端意外退出以后,这个信道会死掉。
然后客户端无法再登陆,提示信道错误。任何一个人也都无法连接使用,必须重新把服务器退出然后再启动。
1.请问大家有什么好的办法能及时知道客户端意外断线了。
2.服务器端如何扫描所有的信道,检查哪个信道阻塞了,已经无法使用的然后再删除掉(意思是,服务器端是否可以向这个通道发送一个包,根据这个包的状态判断这个信道是否正常)
3.我登陆的客户端都是保存在服务器端的 list表里面, 客户端直接取不出来这个list 请教如何返回这个。
[解决办法]
1. duplex的话,可以加上Channel.Closing事件监听。
OperationContext.Current.Channel.Closing += new EventHandler(Channel_Closing);
http://blog.csdn.net/fangxinggood/archive/2011/01/15/6142861.aspx
2. 应该让客户端发送心跳给服务端,服务端检查是否活动链接。
3. 不明白客户端想要什么。
参考:
http://topic.csdn.net/u/20110304/14/705fc930-3e17-4e04-81ee-d56b15162c33.html
[解决办法]
当时是不会,但是有inactivityTimeout啊,超时的时候还是会触发这个事件的。
[解决办法]
把你的 WCF 服务好好描述下,比如:ServiceBehavior的InstanceMode, 用到Duplex了吗?
[解决办法]
看这文章,不过好像也没有结果:
http://www.cnblogs.com/Jax/archive/2009/02/11/1388076.html
[解决办法]
看了看,有个bug的:
if (!_callback.Contains(guest))
{
_callback.Remove(guest);
_userinfo.Remove(strGuest);
}
退出后,仍然会通知一个已经退出的客户端。
但这应该不是问题关键。看了配置文件,没有inactivityTimeout的配置。
是否和这有关?
[解决办法]
查了下msdn:
通道上的活动定义为接收应用程序或基础结构消息。 非活动超时属性会控制保持非活动会话存在的最长时间。 如果超过 InactivityTimeout 指定的时间间隔后仍没有活动,则基础结构会中止会话,且通道会出错。 可靠会话会遭到单方面撤销。
如果发送应用程序没有要发送的消息,则可靠会话通常不会因处于非活动状态而出错,“保持活动状态”机制会让会话无限期地处于活动状态。 请注意,如果未发送或接收任何应用程序消息,则调度程序可以单独中止可靠会话。 因此,如果网络状况为未收到任何类型的消息或发送方失败,则非活动超时通常会过期。
设置此超时可防止服务器在客户端关闭安全会话之前一直保持该会话。 如果安全会话在非活动时间间隔内未收到消息,则服务器会将其关闭。 这样可降低发生拒绝服务攻击的可能性。
使用可靠会话时,必须同时满足两个不同的非活动计时器,才能使连接处于活动状态。 如果任一非活动计时器结束计时,则将断开连接。
第一个非活动计时器为可靠会话计时器,称为 InactivityTimeout。 如果在超时期限内没有收到任何应用程序消息或基础结构消息,此非活动计时器将激发。 基础结构消息是指为了通道堆栈中的协议之一(例如,保持活动状态或确认,而并非包含应用程序数据)而生成的消息。
第二个非活动计时器为服务计时器,它使用绑定的 ReceiveTimeout 设置。 如果在超时期限内没有收到任何应用程序消息,此非活动计时器将激发。
由于任一非活动计时器激发都会断开连接,因此单纯增大 InactivityTimeout(当其大于 ReceiveTimeout 时)不起任何作用。 这两个超时时间的默认值均为 10 分钟,因此在使用可靠会话时,必须同时增大这两个超时时间才会起作用。
还有个 ReceiveTimeout 也应该设置。
[解决办法]
第2个客户端貌似dead lock了。你把他的 JoinRoom 改为 OneWay 试下。我觉得这种callback的,不应该这么用。
[解决办法]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]