Vorgehensweise: Erstellen eines WCF-Diensts, der über WebSockets kommuniziert
WCF-Dienste und -Clients können die NetHttpBinding-Bindung verwenden, um über WebSockets zu kommunizieren. WebSockets werden verwendet, wenn die NetHttpBinding bestimmt, dass der Dienstvertrag einen Rückrufvertrag definiert. In diesem Thema wird das Implementieren eines WCF-Diensts und -Clients beschrieben, die mithilfe der NetHttpBinding über WebSockets kommunizieren.
Definieren des Diensts
Definieren Sie einen Rückrufvertrag.
[ServiceContract] public interface IStockQuoteCallback { [OperationContract(IsOneWay = true)] Task SendQuote(string code, double value); }
Dieser Vertrag wird von der Clientanwendung implementiert, damit der Dienst Nachrichten zurück an den Client senden kann.
Definieren Sie den Dienstvertrag, und geben Sie die
IStockQuoteCallback
-Schnittstelle als Rückrufvertrag an.[ServiceContract(CallbackContract = typeof(IStockQuoteCallback))] public interface IStockQuoteService { [OperationContract(IsOneWay = true)] Task StartSendingQuotes(); }
Implementieren Sie den Dienstvertrag.
public class StockQuoteService : IStockQuoteService { public async Task StartSendingQuotes() { var callback = OperationContext.Current.GetCallbackChannel<IStockQuoteCallback>(); var random = new Random(); double price = 29.00; while (((IChannel)callback).State == CommunicationState.Opened) { await callback.SendQuote("MSFT", price); price += random.NextDouble(); await Task.Delay(1000); } } }
Der Dienstvorgang
StartSendingQuotes
wird als asynchroner Aufruf implementiert. Der Rückrufkanal wird mithilfe desOperationContext
abgerufen, und wenn der Kanal geöffnet ist, wird ein asynchroner Aufruf des Rückrufkanals ausgeführt.Konfigurieren des Diensts
<configuration> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings> <system.web> <compilation debug="true" targetFramework="4.5" /> </system.web> <system.serviceModel> <protocolMapping> <add scheme="http" binding="netHttpBinding"/> <add scheme="https" binding="netHttpsBinding"/> </protocolMapping> <behaviors> <serviceBehaviors> <behavior name=""> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel> </configuration>
Die Konfigurationsdatei des Diensts basiert auf WCF-Standardendpunkten. Mit dem
<protocolMapping>
-Abschnitt wird angegeben, dass für die erstellten Standardendpunkte dieNetHttpBinding
verwendet werden soll.
Definieren des Clients
Implementieren Sie den Rückrufvertrag.
private class CallbackHandler : StockQuoteServiceReference.IStockQuoteServiceCallback { public async Task SendQuoteAsync(string code, double value) { Console.WriteLine("{0}: {1:f2}", code, value); } }
Der Rückrufvertragsvorgang wird als asynchrone Methode implementiert.
Implementieren Sie den Clientcode.
class Program { static void Main(string[] args) { var context = new InstanceContext(new CallbackHandler()); var client = new StockQuoteServiceReference.StockQuoteServiceClient(context); client.StartSendingQuotes(); Console.ReadLine(); } private class CallbackHandler : StockQuoteServiceReference.IStockQuoteServiceCallback { public async Task SendQuoteAsync(string code, double value) { Console.WriteLine("{0}: {1:f2}", code, value); } } }
Der CallbackHandler wird hier aus Gründen der Übersichtlichkeit wiederholt. Die Clientanwendung erstellt einen neuen InstanceContext und gibt die Implementierung der Rückrufschnittstelle an. Danach erstellt sie eine Instanz der Proxyklasse, die einen Verweis an den neu erstellten InstanceContext sendet. Wenn der Client den Dienst aufruft, ruft der Dienst den Client mithilfe des angegebenen Rückrufvertrags auf.
Konfigurieren des Clients
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <system.serviceModel> <bindings> <netHttpBinding> <binding name="NetHttpBinding_IStockQuoteService"> <webSocketSettings transportUsage="Always" /> </binding> </netHttpBinding> </bindings> <client> <endpoint address="ws://localhost/NetHttpSampleServer/StockQuoteService.svc" binding="netHttpBinding" bindingConfiguration="NetHttpBinding_IStockQuoteService" contract="StockQuoteServiceReference.IStockQuoteService" name="NetHttpBinding_IStockQuoteService" /> </client> </system.serviceModel> </configuration>
In der Clientkonfiguration sind keine besonderen Schritte erforderlich. Sie geben einfach den clientseitigen Endpunkt mithilfe der
NetHttpBinding
an.
Beispiel
In Folgenden finden Sie den vollständigen Code, der in diesem Thema verwendet wird.
// IStockQuoteService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace Server
{
[ServiceContract(CallbackContract = typeof(IStockQuoteCallback))]
public interface IStockQuoteService
{
[OperationContract(IsOneWay = true)]
Task StartSendingQuotes();
}
[ServiceContract]
public interface IStockQuoteCallback
{
[OperationContract(IsOneWay = true)]
Task SendQuote(string code, double value);
}
}
// StockQuoteService.svc.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading.Tasks;
namespace Server
{
public class StockQuoteService : IStockQuoteService
{
public async Task StartSendingQuotes()
{
var callback = OperationContext.Current.GetCallbackChannel<IStockQuoteCallback>();
var random = new Random();
double price = 29.00;
while (((IChannel)callback).State == CommunicationState.Opened)
{
await callback.SendQuote("MSFT", price);
price += random.NextDouble();
await Task.Delay(1000);
}
}
}
}
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
https://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
</system.web>
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="netHttpBinding"/>
<add scheme="https" binding="netHttpsBinding"/>
</protocolMapping>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>
<!-- StockQuoteService.svc -->
<%@ ServiceHost Language="C#" Debug="true" Service="Server.StockQuoteService" CodeBehind="StockQuoteService.svc.cs" %>
// Client.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace Client
{
class Program
{
static void Main(string[] args)
{
var context = new InstanceContext(new CallbackHandler());
var client = new StockQuoteServiceReference.StockQuoteServiceClient(context);
client.StartSendingQuotes();
Console.ReadLine();
}
private class CallbackHandler : StockQuoteServiceReference.IStockQuoteServiceCallback
{
public async Task SendQuoteAsync(string code, double value)
{
Console.WriteLine("{0}: {1:f2}", code, value);
}
}
}
}
<!--App.config -->
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<netHttpBinding>
<binding name="NetHttpBinding_IStockQuoteService">
<webSocketSettings transportUsage="Always" />
</binding>
</netHttpBinding>
</bindings>
<client>
<endpoint address="ws://localhost/NetHttpSampleServer/StockQuoteService.svc"
binding="netHttpBinding" bindingConfiguration="NetHttpBinding_IStockQuoteService"
contract="StockQuoteServiceReference.IStockQuoteService" name="NetHttpBinding_IStockQuoteService" />
</client>
</system.serviceModel>
</configuration>