次の方法で共有


双方向サービス

双方向サービス コントラクトは、両方のエンドポイントが互いに独立してメッセージを送信できるメッセージ交換パターンです。 したがって、双方向サービスは、イベントのような動作を提供して、クライアント エンドポイントにメッセージを送信できます。 双方向通信は、クライアントがサービスに接続し、サービスがクライアントにメッセージを送信できるチャネルをサービスに提供するときに発生します。 双方向サービスのイベントに似た動作は、セッション内でのみ機能します。

双方向コントラクトを作成するには、インターフェイスのペアを作成します。 1 つ目は、クライアントが呼び出すことができる操作を記述するサービス コントラクト インターフェイスです。 そのサービス コントラクトでは、ServiceContractAttribute.CallbackContract プロパティでコールバック コントラクトを指定する必要があります。 コールバック コントラクトは、サービスがクライアント エンドポイントで呼び出すことができる操作を定義するインターフェイスです。 双方向コントラクトではセッションは必要ありませんが、システム提供の双方向バインディングではセッションが使用されます。

二重コントラクトの例を次に示します。

[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 クラスは、プライマリ ICalculatorDuplex インターフェイスを実装します。 サービスは、 PerSession インスタンス モードを使用して、各セッションの結果を維持します。 Callbackという名前のプライベート プロパティは、クライアントへのコールバック チャネルにアクセスします。 このサービスは、次のサンプル コードに示すように、コールバック インターフェイスを介してクライアントにメッセージを送信するためにコールバックを使用します。


[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

クライアントは、サービスからメッセージを受信するために、双方向コントラクトのコールバック インターフェイスを実装するクラスを提供する必要があります。 次のサンプル コードは、ICalculatorDuplexCallback インターフェイスを実装するCallbackHandler クラスを示しています。

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

二重コントラクト用に生成される WCF クライアントでは、構築時に InstanceContext クラスを指定する必要があります。 この InstanceContext クラスは、コールバック インターフェイスを実装し、サービスから返されるメッセージを処理するオブジェクトのサイトとして使用されます。 InstanceContext クラスは、CallbackHandler クラスのインスタンスを使用して構築されます。 このオブジェクトは、コールバック インターフェイスでサービスからクライアントに送信されたメッセージを処理します。

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

サービスの構成は、セッション通信と双方向通信の両方をサポートするバインディングを提供するように設定する必要があります。 wsDualHttpBinding要素は、セッション通信をサポートし、双方向通信を可能にします。双方向の HTTP 接続は、方向ごとに 1 つずつ提供されます。

クライアントでは、次のサンプル構成に示すように、サーバーがクライアントへの接続に使用できるアドレスを構成する必要があります。

セキュリティで保護された会話を使用して認証に失敗する非二重クライアントは、通常、 MessageSecurityExceptionをスローします。 ただし、セキュリティで保護された会話を使用する双方向クライアントが認証に失敗した場合、クライアントは代わりに TimeoutException を受け取ります。

WSHttpBinding要素を使用してクライアント/サービスを作成し、クライアント コールバック エンドポイントを含まない場合は、次のエラーが表示されます。

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

次のサンプル コードは、クライアント エンドポイント アドレスをプログラムで指定する方法を示しています。

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

次のサンプル コードは、構成でクライアント エンドポイント アドレスを指定する方法を示しています。

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

Warnung

サービスまたはクライアントがチャネルを閉じると、双方向モデルは自動的に検出されません。 そのため、クライアントが予期せず終了した場合、既定ではサービスには通知されません。または、サービスが予期せず終了した場合、クライアントには通知されません。 切断されたサービスを使用すると、 CommunicationException 例外が発生します。 クライアントとサービスは、独自のプロトコルを実装して、選択した場合に互いに通知することができます。 エラー処理の詳細については、「 WCF エラー処理」を参照してください。

こちらも参照ください