Two-Way 샘플은 MSMQ를 통해 트랜잭션 양방향 큐 통신을 수행하는 방법을 보여 줍니다. 이 샘플에서는 바인딩을 netMsmqBinding
사용합니다. 이 경우 서비스는 대기 중인 메시지를 수신하는 서비스를 관찰할 수 있는 자체 호스팅 콘솔 애플리케이션입니다.
비고
이 샘플에 대한 설치 절차 및 빌드 지침은 이 항목의 끝에 있습니다.
이 샘플은 거래된 MSMQ 바인딩을 기반으로 합니다.
대기 중인 통신에서 클라이언트는 큐를 사용하여 서비스와 통신합니다. 클라이언트는 큐에 메시지를 보내고 서비스는 큐에서 메시지를 받습니다. 따라서 서비스와 클라이언트는 큐를 사용하여 통신하기 위해 동시에 실행될 필요가 없습니다.
이 샘플에서는 큐를 사용하는 2방향 통신을 보여 줍니다. 클라이언트는 트랜잭션 범위 내에서 큐로 구매 주문을 보냅니다. 서비스는 주문을 수신하고, 주문을 처리한 다음, 트랜잭션 범위 내의 큐에서 주문 상태를 사용하여 클라이언트를 다시 호출합니다. 양방향 통신을 촉진하기 위해 클라이언트와 서비스는 구매 주문 및 주문 상태를 처리하기 위해 모두 큐를 사용합니다.
서비스 계약은 IOrderProcessor
큐 사용에 적합한 단방향 서비스 작업을 정의합니다. 서비스 작업에는 주문 상태를 보내는 데 사용할 회신 엔드포인트가 포함됩니다. 회신 엔드포인트는 주문 상태를 클라이언트로 다시 보낼 큐의 URI입니다. 주문 처리 애플리케이션은 이 계약을 구현합니다.
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface IOrderProcessor
{
[OperationContract(IsOneWay = true)]
void SubmitPurchaseOrder(PurchaseOrder po, string
reportOrderStatusTo);
}
주문 상태를 보내는 회신 계약은 클라이언트에 의해 지정됩니다. 클라이언트는 주문 상태 계약을 구현합니다. 서비스는 이 계약의 생성된 프록시를 사용하여 주문 상태를 클라이언트로 다시 보냅니다.
[ServiceContract]
public interface IOrderStatus
{
[OperationContract(IsOneWay = true)]
void OrderStatus(string poNumber, string status);
}
서비스 작업은 제출된 구매 주문을 처리합니다.
OperationBehaviorAttribute는 큐에서 메시지를 수신하는 데 사용되는 트랜잭션의 자동 인리스트먼트를 지정하고, 서비스 작업이 완료될 때 트랜잭션이 자동으로 완료되도록 지정하기 위해 서비스 작업에 적용됩니다. 클래스는 Orders
주문 처리 기능을 캡슐화합니다. 이 경우, 구매 주문을 딕셔너리에 추가합니다. 서비스 작업이 참여한 트랜잭션은 Orders
클래스의 작업에서 사용할 수 있습니다.
서비스 작업은 제출된 구매 주문을 처리하는 것 외에도 주문 상태에 따라 클라이언트에 다시 회신합니다.
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void SubmitPurchaseOrder(PurchaseOrder po, string reportOrderStatusTo)
{
Orders.Add(po);
Console.WriteLine("Processing {0} ", po);
Console.WriteLine("Sending back order status information");
NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding("ClientCallbackBinding");
OrderStatusClient client = new OrderStatusClient(msmqCallbackBinding, new EndpointAddress(reportOrderStatusTo));
// Please note that the same transaction that is used to dequeue the purchase order is used
// to send back order status.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
client.OrderStatus(po.PONumber, po.Status);
scope.Complete();
}
//Close the client.
client.Close();
}
MSMQ 큐 이름은 구성 파일의 appSettings 섹션에 지정됩니다. 서비스의 엔드포인트는 구성 파일의 System.ServiceModel 섹션에 정의되어 있습니다.
비고
MSMQ 큐 이름 및 엔드포인트 주소는 약간 다른 주소 지정 규칙을 사용합니다. MSMQ 큐 이름은 로컬 컴퓨터에 점(.)을 사용하며, 경로에서는 구분 기호로 백슬래시를 사용합니다. WCF(Windows Communication Foundation) 엔드포인트 주소는 net.msmq: 체계를 명시하며, 로컬 컴퓨터에는 "localhost"를 사용하고, 경로에는 슬래시를 사용합니다. 원격 컴퓨터에서 호스트되는 큐에서 읽으려면 "." 및 "localhost"를 원격 컴퓨터 이름으로 바꿉니다.
서비스가 자체 호스팅됩니다. MSMQ 전송을 사용하는 경우 사용되는 큐를 미리 만들어야 합니다. 이 작업은 수동으로 또는 코드를 통해 수행할 수 있습니다. 이 샘플에서 서비스는 큐의 존재를 확인하고 필요한 경우 만듭니다. 큐 이름은 구성 파일에서 읽습니다. 기본 주소는 ServiceModel 메타데이터 유틸리티 도구(Svcutil.exe) 에서 서비스에 대한 프록시를 생성하는 데 사용됩니다.
// Host the service within this EXE console application.
public static void Main()
{
// Get MSMQ queue name from appSettings in configuration.
string queueName = ConfigurationManager.AppSettings["queueName"];
// Create the transacted MSMQ queue if necessary.
if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName, true);
// Create a ServiceHost for the OrderProcessorService type.
using (ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService)))
{
// Open the ServiceHost to create listeners and start listening for messages.
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
}
}
클라이언트가 트랜잭션을 만듭니다. 큐와의 통신은 트랜잭션 범위 내에서 수행되므로 모든 메시지가 성공하거나 실패하는 원자 단위로 처리됩니다.
// Create a ServiceHost for the OrderStatus service type.
using (ServiceHost serviceHost = new ServiceHost(typeof(OrderStatusService)))
{
// Open the ServiceHostBase to create listeners and start listening for order status messages.
serviceHost.Open();
// Create the purchase order.
...
// Create a client with given client endpoint configuration.
OrderProcessorClient client = new OrderProcessorClient("OrderProcessorEndpoint");
//Create a transaction scope.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
string hostName = Dns.GetHostName();
// Make a queued call to submit the purchase order.
client.SubmitPurchaseOrder(po, "net.msmq://" + hostName + "/private/ServiceModelSamplesTwo-way/OrderStatus");
// Complete the transaction.
scope.Complete();
}
//Close down the client.
client.Close();
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
// Close the ServiceHost to shutdown the service.
serviceHost.Close();
}
클라이언트 코드는 서비스에서 주문 상태를 수신하는 계약을 구현 IOrderStatus
합니다. 이 경우 주문 상태를 출력합니다.
[ServiceBehavior]
public class OrderStatusService : IOrderStatus
{
[OperationBehavior(TransactionAutoComplete = true,
TransactionScopeRequired = true)]
public void OrderStatus(string poNumber, string status)
{
Console.WriteLine("Status of order {0}:{1} ", poNumber ,
status);
}
}
주문 상태 큐는 메서드에서 Main
만들어집니다. 클라이언트 구성에는 다음 샘플 구성과 같이 주문 상태 서비스를 호스트하는 주문 상태 서비스 구성이 포함됩니다.
<appSettings>
<!-- Use appSetting to configure MSMQ queue name. -->
<add key="queueName" value=".\private$\ServiceModelSamplesTwo-way/OrderStatus" />
</appSettings>
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.OrderStatusService">
<!-- Define NetMsmqEndpoint -->
<endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderStatus"
binding="netMsmqBinding"
contract="Microsoft.ServiceModel.Samples.IOrderStatus" />
</service>
</services>
<client>
<!-- Define NetMsmqEndpoint -->
<endpoint name="OrderProcessorEndpoint"
address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor"
binding="netMsmqBinding"
contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
</client>
</system.serviceModel>
샘플을 실행하면 서비스 및 클라이언트 콘솔 창에 클라이언트 및 서비스 활동이 모두 표시됩니다. 서비스가 클라이언트에서 메시지를 수신하는 것을 볼 수 있습니다. 각 콘솔 창에서 Enter 키를 눌러 서비스 및 클라이언트를 종료합니다.
서비스는 구매 주문 정보를 표시하고 주문 상태를 주문 상태 큐로 다시 보내고 있음을 나타냅니다.
The service is ready.
Press <ENTER> to terminate service.
Processing Purchase Order: 124a1f69-3699-4b16-9bcc-43147a8756fc
Customer: somecustomer.com
OrderDetails
Order LineItem: 54 of Blue Widget @unit price: $29.99
Order LineItem: 890 of Red Widget @unit price: $45.89
Total cost of this order: $42461.56
Order status: Pending
Sending back order status information
클라이언트는 서비스에서 보낸 주문 상태 정보를 표시합니다.
Press <ENTER> to terminate client.
Status of order 124a1f69-3699-4b16-9bcc-43147a8756fc:Pending
샘플을 설정, 빌드 및 실행하려면
Windows Communication Foundation 샘플 에 대한One-Time 설정 절차를 수행했는지 확인합니다.
솔루션의 C# 또는 Visual Basic .NET 버전을 빌드하려면 Windows Communication Foundation 샘플빌드의 지침을 따릅니다.
단일 또는 컴퓨터 간 구성에서 샘플을 실행하려면 Windows Communication Foundation 샘플실행의 지침을 따릅니다.
비고
Svcutil.exe 사용하여 이 샘플의 구성을 다시 생성하는 경우 클라이언트 구성의 엔드포인트 이름을 클라이언트 코드와 일치하도록 수정해야 합니다.
기본적으로 NetMsmqBinding 전송 보안이 활성화됩니다. MSMQ 전송 보안 MsmqAuthenticationMode 에 대한 두 가지 관련 속성이 있으며 MsmqProtectionLevel.
기본적으로 인증 모드가 설정 Windows
되고 보호 수준이 설정 Sign
됩니다. MSMQ가 인증 및 서명 기능을 제공하려면 도메인의 일부여야 하며 MSMQ에 대한 Active Directory 통합 옵션을 설치해야 합니다. 이러한 조건을 충족하지 않는 컴퓨터에서 이 샘플을 실행하면 오류가 발생합니다.
작업 그룹에 조인된 컴퓨터에서 또는 Active Directory 통합 없이 샘플을 실행하려면
컴퓨터가 도메인에 속하지 않거나 Active Directory 통합이 설치되어 있지 않은 경우 다음 샘플 구성과 같이 인증 모드 및 보호 수준을 설정하여
None
전송 보안을 해제합니다.<configuration> <appSettings> <!-- Use appSetting to configure MSMQ queue name. --> <add key="queueName" value=".\private$\ServiceModelSamplesTwo-way/OrderProcessor" /> </appSettings> <system.serviceModel> <services> <service name="Microsoft.ServiceModel.Samples.OrderProcessorService"> <!-- Define NetMsmqEndpoint --> <endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="Microsoft.ServiceModel.Samples.IOrderProcessor" /> </service> </services> <bindings> <netMsmqBinding> <binding name="TransactedBinding" > <security mode="None" /> </binding> </netMsmqBinding> </bindings> </system.serviceModel> </configuration>
클라이언트 구성에 대한 보안을 해제하면 다음이 생성됩니다.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <!-- Use appSetting to configure MSMQ queue name. --> <add key="queueName" value=".\private$\ServiceModelSamplesTwo-way/OrderStatus" /> </appSettings> <system.serviceModel> <services> <service name="Microsoft.ServiceModel.Samples.OrderStatusService"> <!-- Define NetMsmqEndpoint --> <endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderStatus" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="Microsoft.ServiceModel.Samples.IOrderStatus" /> </service> </services> <client> <!-- Define NetMsmqEndpoint --> <endpoint name="OrderProcessorEndpoint" address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="Microsoft.ServiceModel.Samples.IOrderProcessor" /> </client> <bindings> <netMsmqBinding> <binding name="TransactedBinding" > <security mode="None" /> </binding> </netMsmqBinding> </bindings> </system.serviceModel> </configuration>
이 샘플에 대한 서비스는
OrderProcessorService
에서 바인딩을 만듭니다. 바인딩을 인스턴스화한 후 코드 줄을 추가하여 보안 모드None
를 .로 설정합니다.NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding(); msmqCallbackBinding.Security.Mode = NetMsmqSecurityMode.None;
샘플을 실행하기 전에 서버와 클라이언트 모두에서 구성을 변경해야 합니다.
비고
security mode
를None
로 설정하는 것은 MsmqAuthenticationMode, MsmqProtectionLevel 또는Message
보안을None
로 설정하는 것과 같습니다.