Aracılığıyla paylaş


Çift Yönlü Hizmetler

Çift yönlü hizmet sözleşmesi, her iki uç noktanın da diğerine bağımsız olarak ileti gönderebildiği bir ileti değişimi düzenidir. Bu nedenle çift yönlü bir hizmet istemci uç noktasına ileti göndererek olay benzeri davranışlar sağlayabilir. Çift yönlü iletişim, istemci bir hizmete bağlandığında ve hizmete hizmetin istemciye ileti gönderebileceği bir kanal sağladığında gerçekleşir. Çift yönlü hizmetlerin olay benzeri davranışının yalnızca bir oturum içinde çalıştığını unutmayın.

Çift yönlü anlaşma oluşturmak için bir arabirim çifti oluşturursunuz. Birincisi, bir istemcinin çağırabileceği işlemleri açıklayan hizmet sözleşmesi arabirimidir. Bu hizmet sözleşmesi özelliğinde ServiceContractAttribute.CallbackContract bir geri çağırma sözleşmesi belirtmelidir. Geri çağırma sözleşmesi, hizmetin istemci uç noktasında çağırabileceği işlemleri tanımlayan arabirimdir. Sistem tarafından sağlanan çift yönlü bağlamalar bunları kullansa da, çift yönlü anlaşma oturum gerektirmez.

Aşağıda çift yönlü bir sözleşme örneği verilmiştir.

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required,
                 CallbackContract=typeof(ICalculatorDuplexCallback))]
public interface ICalculatorDuplex
{
    [OperationContract(IsOneWay = true)]
    void Clear();
    [OperationContract(IsOneWay = true)]
    void AddTo(double n);
    [OperationContract(IsOneWay = true)]
    void SubtractFrom(double n);
    [OperationContract(IsOneWay = true)]
    void MultiplyBy(double n);
    [OperationContract(IsOneWay = true)]
    void DivideBy(double n);
}

public interface ICalculatorDuplexCallback
{
    [OperationContract(IsOneWay = true)]
    void Equals(double result);
    [OperationContract(IsOneWay = true)]
    void Equation(string eqn);
}
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required, CallbackContract:=GetType(ICalculatorDuplexCallback))> _
Public Interface ICalculatorDuplex
    <OperationContract(IsOneWay:=True)> _
    Sub Clear()
    <OperationContract(IsOneWay:=True)> _
    Sub AddTo(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub SubtractFrom(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub MultiplyBy(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub DivideBy(ByVal n As Double)
End Interface


Public Interface ICalculatorDuplexCallback
    <OperationContract(IsOneWay:=True)> _
    Sub Equals(ByVal result As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub Equation(ByVal eqn As String)
End Interface

CalculatorService sınıfı birincil ICalculatorDuplex arabirimini uygular. Hizmet, her oturum için PerSession sonucu korumak için örnek modunu kullanır. adlı Callback özel bir özellik, istemciye geri çağırma kanalına erişir. Hizmet, aşağıdaki örnek kodda gösterildiği gibi geri çağırma arabirimi aracılığıyla istemciye ileti göndermek için geri çağırmayı kullanır.


[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorDuplex
{
    double result = 0.0D;
    string equation;

    public CalculatorService()
    {
        equation = result.ToString();
    }

    public void Clear()
    {
        Callback.Equation(equation + " = " + result.ToString());
        equation = result.ToString();
    }

    public void AddTo(double n)
    {
        result += n;
        equation += " + " + n.ToString();
        Callback.Equals(result);
    }

    public void SubtractFrom(double n)
    {
        result -= n;
        equation += " - " + n.ToString();
        Callback.Equals(result);
    }

    public void MultiplyBy(double n)
    {
        result *= n;
        equation += " * " + n.ToString();
        Callback.Equals(result);
    }

    public void DivideBy(double n)
    {
        result /= n;
        equation += " / " + n.ToString();
        Callback.Equals(result);
    }

    ICalculatorDuplexCallback Callback
    {
        get
        {
            return OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
        }
    }
}

<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)> _
Public Class CalculatorService
    Implements ICalculatorDuplex
    Private result As Double = 0.0R
    Private equation As String

    Public Sub New()
        equation = result.ToString()
    End Sub

    Public Sub Clear() Implements ICalculatorDuplex.Clear
        Callback.Equation(equation & " = " & result.ToString())
        equation = result.ToString()
    End Sub

    Public Sub AddTo(ByVal n As Double) Implements ICalculatorDuplex.AddTo
        result += n
        equation &= " + " & n.ToString()
        CType(Callback, Object).Equals(result)
    End Sub

    Public Sub SubtractFrom(ByVal n As Double) Implements ICalculatorDuplex.SubtractFrom
        result -= n
        equation &= " - " & n.ToString()
        CType(Callback, Object).Equals(result)
    End Sub

    Public Sub MultiplyBy(ByVal n As Double) Implements ICalculatorDuplex.MultiplyBy
        result *= n
        equation &= " * " & n.ToString()
        CType(Callback, Object).Equals(result)
    End Sub

    Public Sub DivideBy(ByVal n As Double) Implements ICalculatorDuplex.DivideBy
        result /= n
        equation &= " / " & n.ToString()
        CType(Callback, Object).Equals(result)
    End Sub

    Private ReadOnly Property Callback() As ICalculatorDuplexCallback
        Get
            Return OperationContext.Current.GetCallbackChannel(Of ICalculatorDuplexCallback)()
        End Get
    End Property
End Class

İstemci, hizmetten ileti almak için çift yönlü sözleşmenin geri çağırma arabirimini uygulayan bir sınıf sağlamalıdır. Aşağıdaki örnek kod, arabirimini uygulayan ICalculatorDuplexCallback bir CallbackHandler sınıfı gösterir.

public class CallbackHandler : ICalculatorDuplexCallback
{
    public void Equals(double result)
    {
        Console.WriteLine("Equals({0})", result);
    }

    public void Equation(string eqn)
    {
        Console.WriteLine("Equation({0})", eqn);
    }
}
Public Class CallbackHandler
    Implements ICalculatorDuplexCallback
    Public Overridable Shadows Sub Equals(ByVal result As Double) Implements ICalculatorDuplexCallback.Equals
        Console.WriteLine("Equals({0})", result)
    End Sub

    Public Sub Equation(ByVal eqn As String) Implements ICalculatorDuplexCallback.Equation
        Console.WriteLine("Equation({0})", eqn)
    End Sub
End Class

Çift yönlü sözleşme için oluşturulan WCF istemcisi, derleme sırasında bir InstanceContext sınıfın sağlanmasını gerektirir. Bu InstanceContext sınıf, geri çağırma arabirimini uygulayan ve hizmetten geri gönderilen iletileri işleyen bir nesne için site olarak kullanılır. Sınıf InstanceContext , sınıfının bir örneğiyle CallbackHandler oluşturulur. Bu nesne, hizmetten istemciye geri çağırma arabiriminde gönderilen iletileri işler.

// Construct InstanceContext to handle messages on callback interface
InstanceContext instanceContext = new InstanceContext(new CallbackHandler());

// Create a client
CalculatorDuplexClient client = new CalculatorDuplexClient(instanceContext);
' Construct InstanceContext to handle messages on callback interface
Dim instanceContext As New InstanceContext(New CallbackHandler())

' Create a client
Dim client As New CalculatorDuplexClient(instanceContext)

Hizmet yapılandırması, hem oturum iletişimini hem de çift yönlü iletişimi destekleyen bir bağlama sağlayacak şekilde ayarlanmalıdır. wsDualHttpBinding öğesi oturum iletişimini destekler ve her yön için bir tane olan çift HTTP bağlantıları sağlayarak çift yönlü iletişime izin verir.

İstemcide, aşağıdaki örnek yapılandırmada gösterildiği gibi sunucunun istemciye bağlanmak için kullanabileceği bir adres yapılandırmanız gerekir.

Not

Güvenli bir konuşma kullanarak kimlik doğrulaması başarısız olan çift yönlü olmayan istemciler genellikle bir MessageSecurityExceptionoluşturur. Ancak, güvenli bir konuşma kullanan çift yönlü bir istemci kimlik doğrulamasında başarısız olursa, istemci bunun yerine bir TimeoutException alır.

öğesini kullanarak WSHttpBinding bir istemci/hizmet oluşturursanız ve istemci geri çağırma uç noktasını eklemezseniz aşağıdaki hatayı alırsınız.

HTTP could not register URL
htp://+:80/Temporary_Listen_Addresses/<guid> because TCP port 80 is being used by another application.

Aşağıdaki örnek kod, istemci uç noktası adresinin program aracılığıyla nasıl belirtileceğini gösterir.

WSDualHttpBinding binding = new WSDualHttpBinding();
EndpointAddress endptadr = new EndpointAddress("http://localhost:12000/DuplexTestUsingCode/Server");
binding.ClientBaseAddress = new Uri("http://localhost:8000/DuplexTestUsingCode/Client/");
Dim binding As New WSDualHttpBinding()
Dim endptadr As New EndpointAddress("http://localhost:12000/DuplexTestUsingCode/Server")
binding.ClientBaseAddress = New Uri("http://localhost:8000/DuplexTestUsingCode/Client/")

Aşağıdaki örnek kod, yapılandırmada istemci uç noktası adresinin nasıl belirtileceğini gösterir.

<client>
    <endpoint name ="ServerEndpoint"
          address="http://localhost:12000/DuplexTestUsingConfig/Server"
          bindingConfiguration="WSDualHttpBinding_IDuplexTest"
            binding="wsDualHttpBinding"
           contract="IDuplexTest" />
</client>
<bindings>
    <wsDualHttpBinding>
        <binding name="WSDualHttpBinding_IDuplexTest"
          clientBaseAddress="http://localhost:8000/myClient/" >
            <security mode="None"/>
         </binding>
    </wsDualHttpBinding>
</bindings>

Uyarı

Çift yönlü model, bir hizmetin veya istemcinin kanalını kapattığı zaman otomatik olarak algılamaz. Bu nedenle, bir istemci beklenmedik bir şekilde sonlandırılırsa, varsayılan olarak hizmete bildirim gösterilmez veya bir hizmet beklenmedik bir şekilde sonlandırılırsa istemciye bildirim yapılmaz. Bağlantısı kesilmiş bir hizmet kullanırsanız, CommunicationException özel durum oluşur. İstemciler ve hizmetler, tercih ederlerse birbirlerini bilgilendirmek için kendi protokollerini uygulayabilir. Hata işleme hakkında daha fazla bilgi için bkz . WCF Hata İşleme.

Ayrıca bkz.