我已经工作了数周,创建了一个客户端/服务器来控制位于服务器端的音乐服务器应用程序,该应用程序由位于LAN上的多个客户端应用程序控制。我成功地让客户端与服务器通信,发送操作音乐服务器的命令,并通过使用回调,回复客户端,以便可以适当地更新所有客户端UI。但问题是,我无法弄清楚如何广播需要从服务器应用程序发送到客户端的其他消息。我希望利用回调方法;但是我无法从服务器端访问它。我是否需要修改或创建另一个提供从服务器到客户端的通信的合同?绑定是否需要修改?正如我之前提到的,我已经真正开展了数周的工作(开始感觉像'年'),并希望能够使这个应用程序的最后一部分工作。有人会引导我朝正确的方向前进吗?
客户端服务参考:
<?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);
}