Bagikan melalui


Layanan Dupleks

Kontrak layanan dupleks adalah pola pertukaran pesan di mana kedua titik akhir dapat mengirim pesan ke yang lain secara independen. Oleh karena itu, layanan dupleks dapat mengirimkan pesan kembali ke titik akhir klien, menciptakan perilaku yang menyerupai peristiwa. Komunikasi dupleks terjadi ketika klien terhubung ke layanan dan menyediakan layanan dengan saluran tempat layanan dapat mengirim pesan kembali ke klien. Perhatikan bahwa perilaku menyerupai peristiwa dari layanan dupleks hanya berfungsi dalam sesi.

Untuk membuat kontrak dupleks, Anda membuat sepasang antarmuka. Yang pertama adalah antarmuka kontrak layanan yang menjelaskan operasi yang dapat dipanggil klien. Kontrak layanan tersebut harus menentukan kontrak panggilan balik di ServiceContractAttribute.CallbackContract properti . Kontrak panggilan balik adalah antarmuka yang menentukan operasi yang dapat dipanggil layanan pada titik akhir klien. Kontrak duplex tidak memerlukan sesi, meskipun pengikatan duplex yang disediakan oleh sistem memanfaatkannya.

Berikut ini adalah contoh kontrak dupleks.

[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

Kelas CalculatorService mengimplementasikan antarmuka utama ICalculatorDuplex. Layanan ini menggunakan mode instans PerSession untuk mempertahankan hasil untuk setiap sesi. Properti privat bernama Callback mengakses saluran panggilan balik ke klien. Layanan ini menggunakan panggilan balik untuk mengirim pesan kembali ke klien melalui antarmuka panggilan balik, seperti yang ditunjukkan dalam kode sampel berikut.


[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

Klien harus menyediakan suatu kelas pemrograman yang mengimplementasikan antarmuka callback dari kontrak dupleks untuk menerima pesan dari layanan. Contoh kode berikut menunjukkan CallbackHandler kelas yang mengimplementasikan ICalculatorDuplexCallback antarmuka.

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

    public void Equation(string eqn)
    {
        Console.WriteLine($"Equation({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

Klien WCF yang dihasilkan untuk kontrak dupleks memerlukan kelas InstanceContext yang harus disediakan saat konstruksi. Kelas ini InstanceContext digunakan sebagai situs untuk objek yang mengimplementasikan antarmuka panggilan balik dan menangani pesan yang dikirim kembali dari layanan. Kelas InstanceContext dibangun dengan sebuah instance dari kelas CallbackHandler. Objek ini menangani pesan yang dikirim dari layanan ke klien pada antarmuka panggilan balik.

// 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)

Konfigurasi untuk layanan harus disiapkan untuk menyediakan pengikatan yang mendukung komunikasi sesi dan komunikasi dupleks. Elemen ini wsDualHttpBinding mendukung komunikasi sesi dan memungkinkan komunikasi dupleks dengan menyediakan koneksi HTTP ganda, satu untuk setiap arah.

Pada klien, Anda harus mengonfigurasi alamat yang dapat digunakan server untuk menyambungkan ke klien, seperti yang ditunjukkan dalam konfigurasi sampel berikut.

Nota

Klien non-dupleks yang gagal mengautentikasi melalui percakapan aman biasanya menghasilkan MessageSecurityException. Namun, jika klien dupleks yang menggunakan percakapan aman gagal mengautentikasi, klien menerima TimeoutException sebagai gantinya.

Jika Anda membuat klien/layanan menggunakan WSHttpBinding elemen dan Anda tidak menyertakan titik akhir panggilan balik klien, Anda akan menerima kesalahan berikut.

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

Kode sampel berikut menunjukkan cara menentukan alamat titik akhir klien secara terprogram.

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/")

Contoh kode berikut menunjukkan cara menentukan alamat titik akhir klien dalam konfigurasi.

<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>

Peringatan

Model dupleks tidak secara otomatis mendeteksi kapan layanan atau klien menutup salurannya. Jadi jika klien secara tak terduga berakhir, secara default layanan tidak akan diberi tahu, atau jika layanan tiba-tiba berakhir, klien tidak akan diberi tahu. Jika Anda menggunakan layanan yang terputus, CommunicationException pengecualian akan dinaikkan. Klien dan layanan dapat menerapkan protokol mereka sendiri untuk saling memberi tahu jika mereka memilih. Untuk informasi selengkapnya tentang penanganan kesalahan, lihat Penanganan Kesalahan WCF.

Lihat juga