- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
你好
也许这看起来很荒谬,但这至少对我来说是个问题
我编写了双工 WCF 服务,在我的服务中我需要获得事件的客户端服务并保存它们,当发生特殊事件时我调用特定的客户端并为其发送一些值。所以我定义字典并在其中保存客户端。 (用这个方法客户端调用)
public static Dictionary<int, IServiceCallbak> ActiveClients;
public void IConnect(int SenderId)
{
if (ActiveClients == null)
ActiveClients = new Dictionary<int, IServiceCallbak>();
Client = OperationContext.Current.GetCallbackChannel<IServiceCallbak>();
if (ActiveClients.Count(ac => ac.Key == SenderId) > 0)
ActiveClients.Remove(SenderId);
ActiveClients.Add(SenderId, Client);
}
然后当我需要从那个字典中找到客户端并调用特定方法时:Client.DoSomthing().
此外,当 Client 想要退出时,它会调用 IDisconnect
方法,该方法将从字典中删除 client。
但是客户端管理自己有问题
在 app.config
中定义的一段时间后服务连接将关闭,您应该更新它然后打开服务。
所以在这种情况下:
1) 是否有任何解决方案可以在客户端自动
重新创建和打开服务对象。
2) 或者在服务器端,当服务想要调用客户端时,从该字典中检查客户端服务对象的状态,并从服务器端重新打开连接 (Ridiculous-solution
)
我认为更好的解决方案是处理建议 1
,我不知道该怎么做!!!。
所以现在的问题是:是否存在执行建议 1 的方法?
之前我在评论中描述了建议 1:
“并自动引用这种情况下的事件(如关闭或中止),但我在 Service-Client 中找不到任何用于执行此操作的东西”
最佳答案
为了防止服务器端关闭连接,您可以在客户端可以定期调用的契约(Contract)中设置一个 Heartbeat() 方法。然而,这并不理想,一方面是因为底层套接字可能会丢失,而这无助于补救。
就您的建议而言 1) 如果在客户端您是从 ClientBase 继承的,那么在您调用路由到服务的方法之前可能不会给出任何问题指示。您必须将调用包装在 try/catch 中,然后使用一些重新连接逻辑:
public class MyClass : ClientBase<IContract>, IContract
{
public void ServiceMethod(String data) {
try {
base.Channel.ServiceMethod(data);
}
catch (CommunicationException ce) {
// Perform some reconnect logic here
base.Channel.ServiceMethod(data);
}
}
}
您对建议 2) 的评论是正确的,如果服务器端和客户端之间有任何防火墙,它们很可能不允许连接
编辑:要扩展我对 1) 的建议,当对服务的调用因 CommunicationException 而失败时,您需要创建一个新连接。最简单的方法是在构造函数中创建服务 channel ,然后在调用失败时创建另一个 channel :
class ServiceClient {
Service1Client mService; // Class generated by VS tool
public ServiceClient()
: base() {
mService = new Service1Client();
}
#region IService1 Members
public string GetData(int value) {
CommunicationState state = mService.State;
if (state == CommunicationState.Closed || state == CommunicationState.Faulted) {
mService = new Service1Client();
}
try {
// Note: The state checked above may not be accurate,
// hence the try...catch
return mService.GetData(value);
}
catch (CommunicationException) {
mService = new Service1Client(); // Reconnect logic
return mService.GetData(value); // If it fails again we are out of luck...
}
}
#endregion
}
编辑2:
在 WCF 中, session 由客户端处理,如果客户端与服务之间的 session 丢失,我知道无法从客户端或服务恢复该 session 。不幸的是,你被困在这里。
如果服务想在 session 中断时通过回调发送,简单地说,它不能。由于网络的工作方式,服务可能不知道实际的客户端地址。这个问题和其他各种问题(如防火墙)意味着尝试从服务重新建立到客户端的连接是不切实际的。服务的唯一方法是存储要发送给客户端的数据,并在服务检测到客户端已重新连接时发送。
无法保证客户端会知道底层套接字丢弃,直到客户端尝试通过套接字发送某些内容,因此才会出现 try...catch。一旦意识到连接断开,从客户端重新创建 channel 是我所知道的处理问题的唯一方法;这就是代码示例的作用。
心跳思想是一种主动处理断开连接的方法。它的效率取决于您对检测断开连接的速度以及存在的客户端数量的要求。连接的客户端越多,心跳就必须越长,这样您就不会在服务的网络上增加负载。
编辑3:
经过一些额外的挖掘,可能会有一种方法可以自动执行您想要的操作。您可以创建所谓的 Reliable Session .激活它涉及在配置中创建额外的条目:
<netTcpBinding>
<binding>
<reliableSession ordered="Boolean"
inactivityTimeout="TimeSpan"
enabled="Boolean" />
</binding>
</netTcpBinding>
它也可用于与 Http 相关的绑定(bind),请查看有关该功能的 Microsoft 文档的链接。
关于Wcf 双工 : Retrieve Client Connection?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3986347/
我正在寻找一个跨平台的 C++ master/worker 库或工作队列库。一般的想法是我的应用程序将创建某种任务或工作对象,将它们传递给工作主机或工作队列,这将依次在单独的线程或进程中执行工作。为了
我是一名优秀的程序员,十分优秀!