【问题标题】:WCF server/client count of clients客户端的 WCF 服务器/客户端计数
【发布时间】:2012-04-02 09:43:16
【问题描述】:

我在 WCF 中制作了服务器/客户端应用程序。 如何获取已连接客户端的数量?我怎样才能向每个人发送客户订单?例如:Serwer 向每个客户端发送其他要添加的号码。

Client1 - 1+2=3
Client2 - 1+3=4
Client3 - 1+4=5

并将结果发送到服务器,服务器添加来自客户端的每个结果我返回值 (12)。

我的简单应用:

/////已编辑 /////

服务器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Interface;

namespace WCFapp
{
    class Program
    {
        static void Main(string[] args)
        {
            Klienci cust = new Klienci();
            cust.Connect();
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Interface;

namespace WCFapp
{
     [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
class Klienci : IMessage
{
    private static List<ImessageCallback> subscribers =
        new List<ImessageCallback>();

    public void lista()
    {
        string nm = Console.ReadLine();
        if (nm == "1")
        {
            Console.WriteLine("Number of conected clients: " + subscribers.Count());
            funkcja();

        }
    }

    public void Connect()
    {
        using (ServiceHost host = new ServiceHost(
            typeof(Klienci), new Uri("net.tcp://localhost:8000")))
        {
            host.AddServiceEndpoint(typeof(IMessage),
                new NetTcpBinding(), "ISubscribe");

            try
            {
                host.Open();
                lista();
                Console.ReadLine();
                host.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

    public bool Subscribe()
    {
        try
        {
            ImessageCallback callback = OperationContext.Current.GetCallbackChannel<ImessageCallback>();
            if (!subscribers.Contains(callback))
                subscribers.Add(callback);
            Console.WriteLine("Client is conected ({0}).", callback.GetHashCode());
            return true;
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            return false;
        }
    }

    public bool Unsubscribe()
    {
        try
        {
            ImessageCallback callback = OperationContext.Current.GetCallbackChannel<ImessageCallback>();
            if (subscribers.Contains(callback))
                subscribers.Remove(callback);
            Console.WriteLine("Client is unconected ({0}).", callback.GetHashCode());
            return true;
        }
        catch
        {
            return false;
        }
    }

    public void funkcja()
    {
        int a = 1; int b = 3;
        subscribers.ForEach(delegate(ImessageCallback callback)
        {
            if (((ICommunicationObject)callback).State == CommunicationState.Opened)
            {
            Console.WriteLine("a= {0} , b= {1}", a, b);
            callback.klient_licz(a, b);
            a++;
            b++;
            }
        });

    }

    public void polacz(int S)
    {

        Console.WriteLine("Sum: {0}", S);
    }
  }
}

界面:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;


namespace Interface
{
     [ServiceContract(CallbackContract = typeof(ImessageCallback), SessionMode = SessionMode.Required)]
public interface IMessage
{
    [OperationContract]
    void funkcja();

    [OperationContract]
    void polacz(int S);

    [OperationContract]
    bool Subscribe();

    [OperationContract]
    bool Unsubscribe();

}
[ServiceContract]
public interface ImessageCallback
{
    [OperationContract]
    void klient_licz(int a, int b);
}

}

客户:

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Interface;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            clients cl = new clients();
            if (cl.Conect() == true)
            {
                string tmp = Console.ReadLine();
                while (tmp != "EXIT")
                {
                    cl.SendMessage(tmp);
                    tmp = Console.ReadLine();
                }

            }
             cl.Close();
             Environment.Exit(0);
       }
   }
}

.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Interface;

namespace Client
{
    class clients : ImessageCallback, IDisposable
    {
        IMessage pipeProxy = null;
        public bool Conect()
        {
            DuplexChannelFactory<IMessage> pipeFactory =
                new DuplexChannelFactory<IMessage>(
                    new InstanceContext(this),
                    new NetTcpBinding(),
                    new EndpointAddress("net.tcp://localhost:8000/ISubscribe"));
            try
            {
                pipeProxy = pipeFactory.CreateChannel();
                pipeProxy.Subscribe();
               return true;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return false;
            }

        }

        public void Close()
        {
            pipeProxy.Unsubscribe();
        }


        public void klient_licz(int a, int b)
        {
            int S = a + b;
            Console.WriteLine("Sum= {0}", S);
            pipeProxy.polacz(S); //ERROR
        }

    }
}

我编辑了代码。现在我在 pipeproxy.polacz(S);函数;/

This operation would deadlock because the reply cannot be received until the current Message completes processing. If you want to allow out-of-order message processing, specify ConcurrencyMode of Reentrant or Multiple on CallbackBehaviorAttribute.

【问题讨论】:

    标签: c# wcf client


    【解决方案1】:

    服务器负责缓存客户端列表。通常这将是一个客户端回调接口列表:

    List<IClientCallback> clients; 
    

    通常,您从传入的客户端调用(通常在特定的服务器方法中,如“RegisterClient” - 但可以是服务器上的任何传入调用)填充它:

    IClientCallback callback = OperationContext.Current.GetCallbackChannel<IClientCallback>();              
    if (!clients.Contains(callback))
        clients.Add(callback);
    

    要管理对客户端的广播,您需要一个通用方法来回调客户端列表中所有客户端的特定方法:

    void CallbackAllClients(Action<IClientCallback> action) {
        for (int i=clients.Count-1; i >= 0; i--) {
            IClientCallback callback = clients[i];
            if (((ICommunicationObject)callback).State == CommunicationState.Opened) {
                try {
                    action(callback);
                }
                catch (Exception e) {
                    clients.RemoveAt(i);
                }
            }
            else
                clients.RemovaAt(i);
        }
    }
    

    您可以从服务器代码中调用它来向所有客户端广播客户端回调:

    void SomeServerSideEventHandler(MyObject my_obj) {
        CallbackAllClients(client => client.MyObjectChanged(my_obj));
    } 
    

    其中MyObjectChanged 是客户端回调接口IClientCallback 上的一个方法。 这应该让你大部分时间。

    【讨论】:

    • 我理解这个有点问题。我在界面中创建了新界面IClientCallback。在服务器中,我创建了一个新的class klient : IClientCallback 并创建了新方法`void RegistryClient()`,我将List&lt;IClientCallback&gt; clients; 和此方法-IClientCallback callback = .... 放入客户端RegistryClient() 方法之后。我的理解正确吗?对不起我的英语......我写不出我脑子里的东西。
    • IClientCallback 用于客户端上的服务器回调。它应该由客户端或客户端中的对象实现。一旦服务器对特定客户端的 IClientCallback 有一个引用,它就可以通过该接口联系客户端。服务器隐含 RegisterClient。在连接时,客户端在服务器接口上调用 RegisterClient。服务器端的实现将客户端 ICientCallback 接口存储在列表中。我认为您需要阅读一些关于 WCF 回调的内容。顺便说一句,具有回调接口的服务器将需要双工传输,例如 wsDualHttpBinding 或 NetTCPBinding
    • 我读到了回调,做了一些例子。我编辑了我的所有代码。但现在我在函数 pipeProxy.polacz(S); 中遇到异常; This operation would deadlock because the reply cannot be received until the current Message completes processing. If you want to allow out-of-order message processing, specify ConcurrencyMode of Reentrant or Multiple on CallbackBehaviorAttribute.
    • 没有这个功能它工作正常,但我现在不知道如何在没有这个功能的情况下将结果发送回服务器...... ;/
    • 我建议您将其作为一个单独的问题提出(答案是直截了当的,但它并不是在commnet 中给出它的真正地方)。如果对您有帮助,请接受此答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多