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