2012-04-02 3 views
1

Я сделал сервер/клиентское приложение в WCF. Как получить количество подключенных клиентов? И как я могу отправить всем клиентам другую работу? Например: Serwer посылает каждому клиенту другие номера для добавления.Количество клиентов/клиентов WCF клиентов

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.

ответ

4

Это серверы responsablity кэшировать список клиентов. Как правило, это будет список клиента обратного вызова интерфейсов:

List<IClientCallback> clients; 

Обычно вы заполнить это из входящего клиентского вызова (часто в конкретном методе сервера, как «RegisterClient» - но может быть любой входящий вызов на сервере):

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

для управления вещания для клиентов, которых вы хотите общий метод обратного вызова particualr метод на всех клиентов, в списке клиентов:

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. Это должно сделать вам большую часть пути.

+0

У меня есть небольшая проблема, чтобы понять это. Я создаю новый интерфейс 'IClientCallback' в интерфейсе. На сервере я создаю новый 'class klient: IClientCallback' и создаю новый метод' void RegistryClient() ', где я помещаю' List клиенты; 'и этот метод -' IClientCallback callback = .... 'после этого я помещаю в метод 'RegistryClient()' клиента. Мое понимание правильно? Извините за мой английский ... У меня проблема написать то, что у меня в голове. – user1031034

+1

IClientCallback предназначен для обратного вызова сервера на вашем клиенте. Он должен быть имплантирован клиентом или объектом на клиенте. Как только сервер имеет ссылку на IClientCallback для конкретного клиента, он может связаться с клиентом через этот интерфейс.Сервер внедряет RegisterClient. При подключении клиент вызывает RegisterClient на интерфейсе сервера. На стороне сервера подразумевается интерфейс клиентов ICientCallback в списке. Я думаю, вам нужно немного почитать ответы на вызовы WCF. BTW сервер с интерфейсом обратного вызова потребует дуплексного транспорта, например wsDualHttpBinding или NetTCPBinding – Ricibob

+0

Я читал о обратном вызове, сделал несколько примеров. Я редактировал весь код. Но теперь я получаю исключение в функции pipeProxy.polacz (S); 'Эта операция была бы тупиковой, потому что ответ не может быть получен до тех пор, пока текущее сообщение не завершит обработку. Если вы хотите разрешить обработку сообщений не по порядку, укажите ConcurrencyMode реентерабельного или множественного на CallbackBehaviorAttribute.' – user1031034

Смежные вопросы