c# - 在 Mono Mac 上调用 WCF 客户端通道上的 Close() 超时,但在 Windows 上有效
问题描述
我有一个使用 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));
解决方案
You're running on the latest version of Mono to see if there are any problems.
If this fails,I suggest you upload a complete bug record of the test to: https://bugzilla.xamarin.com/
Thanks.
推荐阅读
- c# - 您可以从另一个查询中调用查询吗?
- php - 在 Laravel 中建立有条件的 Eloquent 关系
- python - Images will not be displayed on flask using loop
- android - 在我的应用程序中,微调项目选择是强制性的。如果用户没有选择任何项目,我如何向用户显示错误?
- django - 如何在 Django F 表达式中将日期和时间字段合并到 DateTime 字段中
- python - 如何将 N 个多列表合并为一个大的多列表?
- arrays - 快速调用解析函数失败
- r - 如何在 R 中绘制稀疏矩阵?
- r - How do I subset a list with mixed data type and data structure?
- elasticsearch - Elasticsearch term query to number token