在 Mono Mac 上调用 WCF 客户端通道上的 Close() 超时,但在 Windows 上有效
Posted
技术标签:
【中文标题】在 Mono Mac 上调用 WCF 客户端通道上的 Close() 超时,但在 Windows 上有效【英文标题】:Calling Close() on WCF client channel times out on Mono Mac but works on Windows 【发布时间】:2021-09-25 06:20:18 【问题描述】:我有一个使用 NetTCP 绑定在 Windows(.Net 框架 4.8)上运行的 WCF 服务器。我有 Windows 和 Mac 客户端。 Windows 和 Mac 客户端使用相同的代码。 Windows 客户端在 .Net framework 4.8 上运行,Mac 客户端在 Mono 6.12.0.122 上运行。
客户端很简单:
连接到服务器 在服务器上调用命令 关闭与服务器的连接它在 Windows 客户端上运行良好,但在 Mac 客户端上,对 Close() 的调用总是在 1 分钟后超时。注意:在这两种情况下,服务器在从客户端发送后立即看到断开连接。
为什么在 Mac 客户端调用 Close() 会超时,即使它与 Windows 客户端的代码相同?
非常感谢任何关于为什么会发生这种情况的建议。
客户端代码:
ChannelFactory<IMyServerInterface> channelFactory;
internal IMyServerInterface channel;
internal MyConnection(string serverIPAddress, int serverPort)
this.serverIPAddress = serverIPAddress;
this.serverPort = serverPort;
try
NetTcpBinding binding = new NetTcpBinding
SendTimeout = TimeSpan.FromSeconds(120),
CloseTimeout = TimeSpan.FromSeconds(20),
Security = new NetTcpSecurity
Mode = SecurityMode.None,
,
;
InstanceContext instanceContext = new InstanceContext(this);
EndpointAddress endpointAddress = new EndpointAddress($"net.tcp://serverIPAddress:serverPort");
channelFactory = new DuplexChannelFactory<IMyServerInterface>(instanceContext, binding, endpointAddress);
catch (Exception ex)
Log.File.Debug(ex, "WCF exception");
internal void Connect()
channel = channelFactory?.CreateChannel();
((IContextChannel)channel).Closed += (sender, e) => OnConnectionLost("Connection closed", CommunicationState.Closed); ;
((IContextChannel)channel).Faulted += (sender, e) => OnConnectionLost("Connection faulted", CommunicationState.Faulted); ;
Log.File.Debug("Calling HandShake..");
Result res = channel?.HandShake();
if (res?.Success == true)
Log.File.Debug($"Connected to server at serverIPAddress:serverPort");
else
throw new Exception("Handshake to server failed" + (res == null? "": $": res.Description"));
internal void CloseChannel()
Log.File.Debug($"CloseChannel");
var channelRef = (ICommunicationObject)channel;
channel = null;
if (channelRef != null)
try
Log.File.Debug($"CloseChannel: Calling Close() on channel");
channelRef.Close();
catch (Exception ex)
Log.File.Debug($"CloseChannel: ex.GetType(): ex.Message");
Log.File.Debug($"CloseChannel: Calling Abort() on channel");
channelRef.Abort();
Log.File.Debug($"CloseChannel finished");
我的客户有以下行为:
[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Single, AutomaticSessionShutdown = true)]
我的服务有以下行为:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, AutomaticSessionShutdown = true, IncludeExceptionDetailInFaults = true) ]
调用 MyConnection()、Connect()、CloseChannel() 会导致:
2021-07-16 12:30:10.9576 | Calling HandShake..
2021-07-16 12:30:11.6284 | Connected to server at 192.168.10.2:5154
2021-07-16 12:30:11.6644 | CloseChannel
2021-07-16 12:30:11.6648 | CloseChannel: Calling Close() on channel
2021-07-16 12:31:11.6746 | CloseChannel: System.TimeoutException: The operation has timed out. <-- Why??!
2021-07-16 12:31:11.6762 | CloseChannel: Calling Abort() on channel
2021-07-16 12:31:11.6807 | OnConnectionLost: Connection closed
2021-07-16 12:31:11.6811 | CloseChannel finished
我不确定这是否相关,但在 Windows 和 Mac 客户端上运行 Wireshark 表明,当连接关闭时,Windows 客户端向服务器发送 TCP RST,而 Mac 客户端向服务器发送 FIN(并且服务器用它自己的 FIN 回复):
窗户:
苹果:
次要问题是未应用以下 CloseTimeout 设置(默认为 1 分钟后超时):
CloseTimeout = TimeSpan.FromSeconds(20)
但是,如果我在 Close() 的参数中设置它,即改变它,它确实会被应用:
channelRef.Close();
收件人:
channelRef.Close(TimeSpan.FromSeconds(20));
【问题讨论】:
【参考方案1】:您正在运行最新版本的 Mono,看看是否有任何问题。
如果失败,建议你上传完整的测试bug记录到:https://bugzilla.xamarin.com/
谢谢。
【讨论】:
谢谢@佳瑶。我在github.com/mono/mono/issues/21163 创建了一个错误报告以及一个显示问题的简单示例项目(在 MacOS 上运行的相同代码在通道上调用 Close() 时挂起)。 如果任何查看此线程的人想查看 github 链接上的示例项目,我将不胜感激。但是,我只能认为这是 Mono 中的一个错误。 我同意你的看法,感谢你的评论。以上是关于在 Mono Mac 上调用 WCF 客户端通道上的 Close() 超时,但在 Windows 上有效的主要内容,如果未能解决你的问题,请参考以下文章
使用 mono 2.10.2 在 mod_mono 上安装 WCF
在特定服务器上调用 WCF 服务时,“无法为具有权限的 ssl/tls 建立安全通道”
WCF:无法为 SSL/TLS 安全通道建立信任关系,出现权限错误