双向WCF客户端 - 服务器通信

问题描述:

我一直在创建一个客户端/服务器来控制位于服务器端的音乐服务器应用程序,该应用程序由位于局域网内的多个客户端应用程序控制。我已经成功地让客户端与服务器进行通信,发送命令来操作音乐服务器,并且通过使用回调来回复客户端,以便所有客户端UI都能够得到适当的更新。然而,我的问题是,我无法弄清楚如何广播需要从服务器应用程序发送到客户端的其他消息。我曾希望利用回调方法;但是我无法从服务器端访问它。我是否需要修改或创建另一个提供从服务器到客户端的通信的合同?绑定是否需要修改?正如我前面提到的那样,我真的一直在为此工作数周(开始感觉像'岁月'),并希望得到最后一块应用程序的工作。请有人引导我走向正确的方向吗?双向WCF客户端 - 服务器通信

客户端服务引用:

<?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> 

客户端AP 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); 
    } 

我想你可以按照this link理解的机制。

NLV