gpt4 book ai didi

WCF 双工 TCP 通信错误

转载 作者:行者123 更新时间:2023-12-04 06:03:25 25 4
gpt4 key购买 nike

我有一个示例服务来测试 WCF net.tcp 通信。这是一个非常简单的服务,它所做的只是为客户端订阅服务,然后调用回调 channel 来通知所有连接的客户端有关广播消息的信息。该服务托管在 IIS 7.5 中。

这是服务代码和测试客户端来测试它。

[ServiceContract(CallbackContract = typeof(ISampleServiceCallBack), SessionMode = SessionMode.Required)]
public interface ISampleCuratioService
{
[OperationContract(IsOneWay = true)]
void SubcribeToService(string sub);

[OperationContract]
string GetData(int value);

[OperationContract(IsOneWay = true)]
void Broadcast(string message);
}

public interface ISampleServiceCallBack
{
[OperationContract(IsOneWay = true)]
void NotifyClient(string message);
}

这是服务实现:
[ServiceBehavior(Name = "CuratioCSMService", InstanceContextMode = InstanceContextMode.PerSession)]
public class Service1 : ISampleCuratioService
{
private static List<ISampleServiceCallBack> JoinedClien = new List<ISampleServiceCallBack>();

public void SubcribeToService(string sub)
{
var subscriber = OperationContext.Current.GetCallbackChannel<ISampleServiceCallBack>();
if (!JoinedClien.Contains(subscriber))
{
JoinedClien.Add(subscriber);
}
}

public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}

public void Broadcast(string message)
{
JoinedClien.ForEach(c => c.NotifyClient("message was received " + message));
}
}

我无法理解运行它时的行为。第一个客户端运行后一切正常,但是当我关闭并打开测试客户端应用程序时,它会抛出异常通知 channel 不能用于通信,因为它处于故障状态。

这是示例测试客户端:
    static void Main(string[] args)
{
var callneckclient = new ServiceClientProxy();
var client = new SampleCuratioServiceClient(new InstanceContext(callneckclient));
client.SubcribeToService("me");
Console.ReadLine();

for (int i = 0; i < 15; i++)
{
Console.WriteLine(client.GetData(5));
client.Broadcast("this is from client me");
}
client.Close();
Console.Read();
}

public class ServiceClientProxy : ISampleCuratioServiceCallback, IDisposable
{
public void NotifyClient(string message)
{
Console.WriteLine(message);
}

public void Dispose()
{
GC.SuppressFinalize(this);
}
}

当我运行 5 个客户端时,情况变得更加糟糕。这些都不是发送或接收消息。

最佳答案

当客户调用SubcribeToService您将其操作上下文添加到名为 JoinedClien 的列表中.

当您调用 Broadcast在您的服务器中,您调用方法 NotifyClient在曾经连接过的每个客户端的所有收集的操作上下文上。

问题是,断开连接的客户端不会从您的 JoinedClien 中删除。列表。
当您尝试在断开连接的操作上下文上调用操作方法时,您会得到 channel 处于故障状态错误。

要解决此问题,您应该订阅 Channel_ClosedChannel_Faulted事件,还 catch CommunicationException当回调您的客户端并删除故障客户端的操作上下文时:

public void Broadcast(string message)
{
// copy list of clients
List<OperationContext> clientsCopy = new List<OperationContext>();
lock(JoinedClien) {
clientsCopy.AddRange(JoinedClien);
}

// send message and collect faulted clients in separate list
List<OperationContext> clientsToRemove = new List<OperationContext>();
foreach (var c in JoinedClien)
{
try {
c.NotifyClient("message was received " + message));
}
catch (CommunicationException ex) {
clientsToRemove.Add(c);
}
}

foreach (var c in clientsToRemove)
{
lock(JoinedClien) {
if(JoinedClien.Contains(c))
JoinedClien.Remove(c);
}
}
}

添加新客户端时,您也必须锁定该操作:
var subscriber = OperationContext.Current.GetCallbackChannel<ISampleServiceCallBack>();
lock(JoinedClien)
{
if (!JoinedClien.Contains(subscriber))
{
JoinedClien.Add(subscriber);
}
}

关于WCF 双工 TCP 通信错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8672061/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com