Je travaille depuis plusieurs semaines sur la création d'un client/serveur pour contrôler une application serveur de musique située sur le serveur et contrôlée par plusieurs applications clientes situées sur le réseau local. J'ai réussi à faire en sorte que le côté client communique avec le serveur, en envoyant des commandes pour faire fonctionner le serveur de musique, et en utilisant des rappels, je réponde aux clients afin que toutes les interfaces client puissent être correctement mises à jour. Mon problème est cependant que je n'arrive pas à comprendre comment diffuser d'autres messages qui doivent être envoyés de l'application serveur aux clients. J'espérais utiliser la méthode de rappel; Cependant, je n'ai pas pu y accéder du côté serveur. Ai-je besoin de modifier ou de créer un autre contrat permettant la communication du serveur aux clients? La reliure nécessite-t-elle une modification? Comme je l'ai mentionné plus tôt, j'y ai vraiment travaillé pendant des semaines (ce qui commence à ressembler à des «années»), et j'espère que cette dernière partie de l'application fonctionnera. Quelqu'un pourrait-il me diriger dans la bonne direction?Communication client-serveur WCF bidirectionnelle
côté RÉFÉRENCE service à la clientèle:
<?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>
côté client 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>
côté serveur 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>
côté serveur 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); });
}
}
côté serveur 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);
}
}
côté serveur - 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);
}