最近在做开发的时候的遇到一个问题,采用WCF做服务端开发,利用的是TCP绑定。因为涉及到大数据量的传输,要求开启可靠会话。
之前的程序中,本身是关闭了可靠会话,然后在服务器端注册了客户端的Closing和Faulted事件:
OperationContext.Current.Channel.Closing += Exit; OperationContext.Current.Channel.Faulted += Exit;
程序运行正常,当客户端出现网络异常中断时(断点,强制结束进程等),可以立即触发事件,调用Exit方法。而当程序在receiveTimeout指定的时间段内,未产生过通信,同样也会触发事件。这里可以把receiveTimeout认为是一个空闲超时。
但是在增加了可靠会话后,情况变得不一样了。客户端正常关闭时,可以立即触发事件,但是异常中断时,Closing和Faulted都没有被触发。Google了一下也没有找到一个合理的解释,那么最有可能的原因是受到了inactivityTimeout的影响。
inactivityTimeout,MSDN上的解释为:获取或设置服务在关闭之前保持非活动状态的时间间隔。
有点难以理解,于是做了一个实验。
同样一个服务,将receiveTimeout设置为1分钟(默认10分钟),将inactivityTimeout设置为10秒钟,启动客户端调试。
如果调用服务器端方法的时间间隔不超过1分钟,那么客户端与服务器将一直保持连接,直到1分钟过后与客户端主动断开连接,则事件被触发。
如果客户端异常断开连接(直接结束进程),则在5-10秒之后,事件被触发。
PS:主动断开连接或超过了receiveTimeout的设定值,只触发Closing事件,如果是超过了inactivityTimeout设定值,还要额外触发Faulted事件。
通过这个实验,大概能理解receiveTimeout和inactivityTimeout的作用以及事件被触发的时机了。
我个人的理解,receiveTimeout是指在客户端和服务器端保持连接的活动期间的空闲超时值,如果在连接的活动期间,客户端和服务器端没有数据交互,并且这个时间段超过了设定值,则服务器会主动断开客户端的连接。
而inactivityTimeout则表示在客户端和服务器端已经断开的情况下的非活动期间的空闲超时值,如果在非活动期间,时间超过了设定值,则会触发事件。
PS:inactivityTimout的时间设置如果超过receiveTimeout的话,是没有意义的。
所以,如果想在客户端断开或异常断开的时候立即触发事件,则将inactivityTimout设置的尽量小,例如5秒,如果想让客户端和服务器端保持长连接时,则将receiveTimeout设置的尽量大,例如1个小时。