Я работал в течение нескольких недель над созданием клиента / сервера для управления приложением музыкального сервера, расположенным на стороне сервера, которое управляется несколькими клиентскими приложениями, расположенными в локальной сети. Мне удалось заставить клиентскую часть взаимодействовать с сервером, посылать команды для управления музыкальным сервером и, используя обратные вызовы, отвечать клиентам, чтобы все клиентские интерфейсы могли быть соответствующим образом обновлены. Моя проблема, однако, в том, что я не могу понять, как передавать другие сообщения, которые должны быть отправлены из серверного приложения клиентам Я надеялся использовать метод обратного вызова; однако я не смог получить к нему доступ со стороны сервера. Нужно ли изменить или создать другой контракт, который предусматривает связь с сервером клиентам? Требуется ли модификация привязки? Как я упоминал ранее, я действительно работал над этим неделями (что начинает ощущаться как «годы»), и надеюсь, что этот последний фрагмент приложения заработает. Кто-нибудь, пожалуйста, направьте меня в правильном направлении?
ОБСЛУЖИВАНИЕ на стороне клиента:
<?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);
}