Двунаправленная связь клиент-сервер WCF - PullRequest
5 голосов
/ 15 мая 2010

Я работал в течение нескольких недель над созданием клиента / сервера для управления приложением музыкального сервера, расположенным на стороне сервера, которое управляется несколькими клиентскими приложениями, расположенными в локальной сети. Мне удалось заставить клиентскую часть взаимодействовать с сервером, посылать команды для управления музыкальным сервером и, используя обратные вызовы, отвечать клиентам, чтобы все клиентские интерфейсы могли быть соответствующим образом обновлены. Моя проблема, однако, в том, что я не могу понять, как передавать другие сообщения, которые должны быть отправлены из серверного приложения клиентам Я надеялся использовать метод обратного вызова; однако я не смог получить к нему доступ со стороны сервера. Нужно ли изменить или создать другой контракт, который предусматривает связь с сервером клиентам? Требуется ли модификация привязки? Как я упоминал ранее, я действительно работал над этим неделями (что начинает ощущаться как «годы»), и надеюсь, что этот последний фрагмент приложения заработает. Кто-нибудь, пожалуйста, направьте меня в правильном направлении?

ОБСЛУЖИВАНИЕ на стороне клиента:

<?xml version="1.0" encoding="utf-8"?>
<ServiceReference>
<ProxyGenerationParameters
    ServiceReferenceUri="http://localhost:8001/APService/mex"
    Name="APGateway"
    NotifyPropertyChange="True"
    UseObservableCollection="False">
</ProxyGenerationParameters>
<EndPoints>
    <EndPoint
        Address="net.tcp://localhost:8000/APService/service"
        BindingConfiguration="TcpBinding"
        Contract="APClient.APGateway.APUserService"
        >
    </EndPoint>
    <EndPoint
        Address="http://localhost:8001/APService/service"
        BindingConfiguration="HttpBinding"
        Contract="APClient.APGateway.APUserService"
        >
    </EndPoint>
</EndPoints>
</ServiceReference>

Клиентская точка доступа CONFIG

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <section name="APClient.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
</configSections>
<system.serviceModel>
    <client>
        <endpoint
            address="net.tcp://localhost:8000/APService/service"
            binding="netTcpBinding"
            contract="APClient.APGateway.APUserService"
            name="TcpBinding" />
        <endpoint
            address="http://localhost:8001/APService/service"
            binding="wsDualHttpBinding"
            contract="APClient.APGateway.APUserService"
            name="HttpBinding" />
    </client>
</system.serviceModel>
<applicationSettings>
    <APClient.Properties.Settings>
        <setting name="pathToDatabase" serializeAs="String">
            <value>C:\Users\Bill\Documents\APData\</value>
        </setting>
    </APClient.Properties.Settings>
</applicationSettings>

AP на стороне сервера. CONFIG

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MetadataBehavior">
           <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8001/APService/mex" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="MetadataBehavior" name="APService.APService">
        <endpoint address="service" binding="netTcpBinding" name="TcpBinding"
          contract="APService.IAPServiceInventory" />
        <endpoint address="service" binding="wsDualHttpBinding" name="HttpBinding"
         contract="APService.IAPServiceInventory" />
        <endpoint address="mex" binding="mexHttpBinding" name="MexBinding"
          contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:8000/APService/" />
            <add baseAddress="http://localhost:8001/APService/" />
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>
</configuration>

Серверная сторона APSERVICE.CS

namespace APService
{
     [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Single,InstanceContextMode=InstanceContextMode.PerCall)]
 public class APService : IAPServiceInventory
 {
      private static List<IClientCallback> _callbackList = new List<IClientCallback>();
      private static int _beerInventory = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["InitialBeerInventory"]);
      public APService() {}
      public int SubscribeToServer(string guestName)
      {
           IClientCallback guest = OperationContext.Current.GetCallbackChannel<IClientCallback>();
           if(!_callbackList.Contains(guest)) { _callbackList.Add(guest); }
           else { Console.WriteLine(guest + " is already logged onto the Server."); }
           _callbackList.ForEach(delegate(IClientCallback callback) { callback.NotifyGuestJoinedParty(guestName); });
      }
      public void UpdateClients(string guestName,string UpdateInfo)
      {
           _callbackList.ForEach(delegate(IClientCallback callback) { callback.NotifyUpdateClients(guestName,UpdateInfo); });
      }
      public void SendRequestToServer(string guestName, string request)
      {
           _callbackList.ForEach(delegate(IClientCallback callback) { callback.NotifyRequestMadeToServer(guestName,request); });
           if(request == "Play") { APControl.Play(); }
           else if(request == "Stop") { APControl.Stop(); }
           else if(request == "Pause") { APControl.PlayPause(); }
           else if(request == "Next Track") { APControl.NextTrack(); }
           else if(request == "Previous Track") { APControl.PreviousTrack(); }
           else if(request == "Mute") { APControl.Mute(); }
           else if(request == "Volume Up") { APControl.VolumeUp(5); }
           else if(request == "Volume Down") { APControl.VolumeDown(5); }
      }
      public void CancelServerSubscription(string guestName)   
      {
           IClientCallback guest = OperationContext.Current.GetCallbackChannel<IClientCallback>();
           if(_callbackList.Contains(guest)) { _callbackList.Remove(guest); }
           _callbackList.ForEach(delegate(IClientCallback callback) { callback.NotifyGuestLeftParty(guestName); });
      }
 }

Серверная часть IAPSERVICE.CS

namespace APService
{
     [ServiceContract(Name="APUserService",Namespace="http://AP.com/WCFClientServer/",SessionMode=SessionMode.Required, CallbackContract=typeof(IClientCallback))]
 public interface IAPServiceInventory
 {
      [OperationContract()]
      int SubscribeToServer(string guestName);
      [OperationContract(IsOneWay=true)]
      void SendRequestToServer(string guestName,string request);
      [OperationContract(IsOneWay=true)]
      void UpdateClients(string guestName,string UpdateInfo);
      [OperationContract(IsOneWay=true)]
      void CancelServerSubscription(string guestName);
 }
 }

Сторона сервера - IAPServiceCallback.cs

namespace APService
{
     public interface IClientCallback
     {
          [OperationContract(IsOneWay=true)]
          void NotifyGuestJoinedParty(string guestName);
          [OperationContract(IsOneWay=true)]
          void NotifyUpdateClients(string guestName,string UpdateInfo);
          [OperationContract(IsOneWay=true)]
          void NotifyRequestMadeToServer(string guestName,string request);
          [OperationContract(IsOneWay=true)]
          void NotifyGuestLeftParty(string guestName);
     }

1 Ответ

1 голос
/ 24 июня 2010

Я думаю, вы можете перейти по этой ссылке , чтобы понять механизм.

NLV

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...