Bagikan melalui


Duplex Services

Kontrak layanan dupleks adalah pola pertukaran pesan di mana kedua titik akhir dapat mengirim pesan independen ke yang lain. Layanan dupleks, oleh karena itu, dapat mengirim pesan kembali ke titik akhir klien, memberikan perilaku seperti peristiwa. Komunikasi dupleks terjadi ketika klien terhubung ke layanan dan menyediakan layanan dengan saluran di mana layanan dapat mengirim pesan kembali ke klien. Perhatikan bahwa perilaku layanan dupleks seperti peristiwa hanya berfungsi dalam satu sesi.

Untuk membuat kontrak dupleks, Anda harus membuat sepasang antarmuka. Pertama, antarmuka kontrak layanan yang menjelaskan operasi yang dapat diminta oleh klien. Kontrak layanan tersebut harus menetapkan kontrak panggilan balik di properti ServiceContractAttribute.CallbackContract. Kontrak panggilan balik adalah antarmuka yang mendefinisikan operasi yang dapat dipanggil layanan pada titik akhir klien. Kontrak dupleks tidak memerlukan sesi, meskipun pengikatan dupleks yang disediakan 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 ICalculatorDuplex utama. Layanan menggunakan mode instans PerSession untuk mempertahankan hasil untuk setiap sesi. Properti pribadi yang dinamai Callback mengakses saluran panggilan balik ke klien. Layanan menggunakan panggilan balik untuk mengirim pesan kembali ke klien melalui antarmuka panggilan balik, seperti yang ditunjukkan dalam kode contoh 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 kelas yang mengimplementasikan antarmuka panggilan balik dari kontrak dupleks, untuk menerima pesan dari layanan. Kode contoh berikut menunjukkan kelas CallbackHandler yang mengimplementasikan antarmuka ICalculatorDuplexCallback.

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

Klien WCF yang dihasilkan untuk kontrak dupleks memerlukan kelas InstanceContext yang akan disediakan saat konstruksi. Kelas InstanceContext ini digunakan sebagai situs untuk objek yang mengimplementasikan antarmuka panggilan balik dan menangani pesan yang dikirim kembali dari layanan. Kelas InstanceContext dibuat dengan turunan 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 diatur untuk menyediakan pengikatan yang mendukung komunikasi sesi dan komunikasi dupleks. Elemen 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 menyambung ke klien, seperti yang diperlihatkan dalam sampel konfigurasi berikut.

Catatan

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

Jika Anda membuat klien/layanan menggunakan elemen WSHttpBinding 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 contoh 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/")

Kode contoh 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 saat layanan atau klien menutup salurannya. Jadi jika klien tiba-tiba berhenti, secara default layanan tidak akan diberitahu, atau jika layanan tiba-tiba berhenti, klien tidak akan diberitahu. Jika Anda menggunakan layanan yang terputus, pengecualian CommunicationException dimunculkan. Klien dan layanan dapat menerapkan protokol mereka sendiri untuk saling memberi tahu jika mereka mau. Untuk informasi selengkapnya tentang penanganan kesalahan, lihat Penanganan Kesalahan WCF.

Lihat juga