WCF(Windows Communication Foundation) 서비스와의 모든 통신은 엔드포인트를 통해 수행됩니다. 각 ServiceEndpoint에는 Address, Binding, Contract가 각각 포함됩니다. 계약은 사용할 수 있는 작업을 지정합니다. 바인딩은 서비스와 통신하는 방법을 지정하고 주소는 서비스를 찾을 위치를 지정합니다. 모든 엔드포인트에는 고유한 주소가 있어야 합니다. 엔드포인트 주소는 서비스의 주소를 나타내는 URI(Uniform Resource Identifier), 서비스의 EndpointAddress보안 ID를 나타내는 URI(Uniform Resource Identifier) 및 선택적 Identity컬렉션이 포함된 클래스로 표시됩니다Headers. 선택적 헤더는 엔드포인트를 식별하거나 상호 작용하는 보다 자세한 주소 지정 정보를 제공합니다. 예를 들어 헤더는 들어오는 메시지를 처리하는 방법, 엔드포인트가 회신 메시지를 보내야 하는 위치 또는 여러 인스턴스를 사용할 수 있는 경우 특정 사용자로부터 들어오는 메시지를 처리하는 데 사용할 서비스 인스턴스를 나타낼 수 있습니다.
엔드포인트 주소 정의
WCF EndpointAddress 에서 WS-Addressing 표준에 정의된 대로 EPR(엔드포인트 참조)을 모델화합니다.
대부분의 전송에 대한 주소 URI에는 네 부분으로 구성됩니다. 예를 들어 이 URI http://www.fabrikam.com:322/mathservice.svc/secureEndpoint
는 다음과 같은 네 부분으로 구성됩니다.
체계: http:
컴퓨터:
www.fabrikam.com
(선택 사항) 포트: 322
경로: /mathservice.svc/secureEndpoint
EPR 모델의 일부는 각 엔드포인트 참조가 추가 식별 정보를 추가하는 몇 가지 참조 매개 변수를 전달할 수 있다는 것입니다. WCF에서 이러한 참조 매개 변수는 클래스의 AddressHeader 인스턴스로 모델링됩니다.
서비스의 엔드포인트 주소는 코드를 사용하여 명령적으로 또는 구성을 통해 선언적으로 지정할 수 있습니다. 배포된 서비스에 대한 바인딩 및 주소는 일반적으로 서비스를 개발하는 동안 사용되는 것과 다르기 때문에 코드에서 엔드포인트를 정의하는 것은 일반적으로 실용적이지 않습니다. 일반적으로 코드보다는 구성을 사용하여 서비스 엔드포인트를 정의하는 것이 더 실용적입니다. 바인딩 및 주소 지정 정보를 코드에서 제외하면 애플리케이션을 다시 컴파일하고 다시 배포하지 않고도 변경할 수 있습니다. 코드 또는 구성에 엔드포인트가 지정되지 않은 경우 런타임은 서비스에서 구현하는 각 계약의 각 기본 주소에 하나의 기본 엔드포인트를 추가합니다.
WCF에서 서비스에 대한 엔드포인트 주소를 지정하는 방법에는 두 가지가 있습니다. 서비스와 연결된 각 엔드포인트에 대한 절대 주소를 지정하거나 서비스의 기본 주소를 제공한 다음 이 기본 주소를 ServiceHost 기준으로 정의된 이 서비스와 연결된 각 엔드포인트의 주소를 지정할 수 있습니다. 이러한 각 절차를 사용하여 구성 또는 코드에서 서비스의 엔드포인트 주소를 지정할 수 있습니다. 상대 주소를 지정하지 않으면 서비스에서 기본 주소를 사용합니다. 서비스에 대한 여러 기본 주소를 가질 수도 있지만 각 서비스는 각 전송에 대해 하나의 기본 주소만 허용됩니다. 각각 다른 바인딩으로 구성된 여러 엔드포인트가 있는 경우 해당 주소는 고유해야 합니다. 동일한 바인딩을 사용하지만 다른 계약을 사용하는 엔드포인트는 동일한 주소를 사용할 수 있습니다.
IIS를 사용하여 호스팅하는 경우 인스턴스를 ServiceHost 직접 관리하지 않습니다. 기본 주소는 항상 IIS에서 호스팅할 때 서비스의 .svc 파일에 지정된 주소입니다. 따라서 IIS 호스팅 서비스 엔드포인트에 대해 상대 엔드포인트 주소를 사용해야 합니다. 정규화된 엔드포인트 주소를 제공하면 서비스 배포에 오류가 발생할 수 있습니다. 자세한 내용은 인터넷 정보 서비스 Services-Hosted WCF 서비스 배포를 참조하세요.
구성에서 엔드포인트 주소 정의
구성 파일에서 엔드포인트를 정의하려면 엔드포인트< 요소를 사용합니다>.
<configuration>
<system.serviceModel>
<services>
<service name="UE.Samples.HelloService"
behaviorConfiguration="HelloServiceBehavior">
<endpoint address="/Address1"
binding="basicHttpBinding"
contract="UE.Samples.IHello"/>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="HelloServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
메서드가 Open 호출되면(즉, 호스팅 애플리케이션이 서비스를 시작하려고 할 때) 시스템은 이름 특성이 "UE.Samples.HelloService"로 지정된 <서비스> 요소를 찾습니다. <서비스> 요소가 발견되면 시스템은 지정된 클래스를 로드하고 구성 파일에 제공된 엔드포인트 정의를 사용하여 엔드포인트를 만듭니다. 이 메커니즘을 사용하면 코드에서 바인딩 및 주소 지정 정보를 유지하면서 두 줄의 코드로 서비스를 로드하고 시작할 수 있습니다. 이 방법의 장점은 애플리케이션을 다시 컴파일하거나 다시 배포하지 않고도 이러한 변경을 수행할 수 있다는 것입니다.
선택적 헤더는 헤더에 <선언됩니다>. 다음은 "Gold" 클라이언트와 "Standard" 클라이언트의 두 헤더를 구분하는 구성 파일에서 http://tempuri1.org/
http://tempuri2.org/
서비스에 대한 엔드포인트를 지정하는 데 사용되는 요소의 예입니다. 이 서비스를 호출하는 클라이언트는 해당 구성 파일에 적절한 <헤더가> 있어야 합니다.
<configuration>
<system.serviceModel>
<services>
<service name="UE.Samples.HelloService"
behaviorConfiguration="HelloServiceBehavior">
<endpoint address="/Address1"
binding="basicHttpBinding"
contract="UE.Samples.IHello">
<headers>
<Member xmlns="http://tempuri1.org/">Gold</Member>
</headers>
</endpoint>
<endpoint address="/Address2"
binding="basicHttpBinding"
contract="UE.Samples.IHello">
<headers>
<Member xmlns="http://tempuri2.org/">Silver</Member>
</headers>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="HelloServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
헤더는 이전에 표시된 것처럼 엔드포인트의 모든 메시지 대신 개별 메시지에 설정할 수도 있습니다. 이 작업은 다음 예제와 같이 클라이언트 애플리케이션에서 새 컨텍스트를 만들어 나가는 메시지에 사용자 지정 헤더를 추가하는 데 사용됩니다 OperationContextScope .
SampleServiceClient wcfClient = new SampleServiceClient(new InstanceContext(this));
try
{
using (OperationContextScope scope = new OperationContextScope(wcfClient.InnerChannel))
{
MessageHeader header
= MessageHeader.CreateHeader(
"Service-Bound-CustomHeader",
"http://Microsoft.WCF.Documentation",
"Custom Happy Value."
);
OperationContext.Current.OutgoingMessageHeaders.Add(header);
// Making calls.
Console.WriteLine("Enter the greeting to send: ");
string greeting = Console.ReadLine();
//Console.ReadLine();
header = MessageHeader.CreateHeader(
"Service-Bound-OneWayHeader",
"http://Microsoft.WCF.Documentation",
"Different Happy Value."
);
OperationContext.Current.OutgoingMessageHeaders.Add(header);
// One-way
wcfClient.Push(greeting);
this.wait.WaitOne();
// Done with service.
wcfClient.Close();
Console.WriteLine("Done!");
Console.ReadLine();
}
}
catch (TimeoutException timeProblem)
{
Console.WriteLine("The service operation timed out. " + timeProblem.Message);
Console.ReadLine();
wcfClient.Abort();
}
catch (CommunicationException commProblem)
{
Console.WriteLine("There was a communication problem. " + commProblem.Message);
Console.ReadLine();
wcfClient.Abort();
}
Dim wcfClient As New SampleServiceClient(New InstanceContext(Me))
Try
Using scope As New OperationContextScope(wcfClient.InnerChannel)
Dim header As MessageHeader = MessageHeader.CreateHeader("Service-Bound-CustomHeader", _
"http://Microsoft.WCF.Documentation", "Custom Happy Value.")
OperationContext.Current.OutgoingMessageHeaders.Add(header)
' Making calls.
Console.WriteLine("Enter the greeting to send: ")
Dim greeting As String = Console.ReadLine()
'Console.ReadLine();
header = MessageHeader.CreateHeader("Service-Bound-OneWayHeader", _
"http://Microsoft.WCF.Documentation", "Different Happy Value.")
OperationContext.Current.OutgoingMessageHeaders.Add(header)
' One-way
wcfClient.Push(greeting)
Me.wait.WaitOne()
' Done with service.
wcfClient.Close()
Console.WriteLine("Done!")
Console.ReadLine()
End Using
Catch timeProblem As TimeoutException
Console.WriteLine("The service operation timed out. " & timeProblem.Message)
Console.ReadLine()
wcfClient.Abort()
Catch commProblem As CommunicationException
Console.WriteLine("There was a communication problem. " & commProblem.Message)
Console.ReadLine()
wcfClient.Abort()
End Try
메타데이터의 엔드포인트 주소
엔드포인트 주소는 WSDL(Web Services Description Language)에서 해당 엔드포인트 요소 내의 EndpointReference
EPR(WS-Addressing wsdl:port
) 요소로 표시됩니다. EPR에는 엔드포인트의 주소와 모든 주소 속성이 포함됩니다. 다음 예제와 같이 wsdl:port
내부의 EPR이 soap:Address
을(를) 대체한다는 점을 참고하세요.
코드에서 엔드포인트 주소 정의
클래스를 사용하여 코드 EndpointAddress 에서 엔드포인트 주소를 만들 수 있습니다. 엔드포인트 주소에 지정된 URI는 정규화된 경로 또는 서비스의 기본 주소를 기준으로 하는 경로일 수 있습니다. 다음 코드에서는 클래스의 EndpointAddress 인스턴스를 만들고 서비스를 호스팅하는 인스턴스에 ServiceHost 추가하는 방법을 보여 줍니다.
다음 예제에서는 코드에서 전체 엔드포인트 주소를 지정하는 방법을 보여 줍니다.
Uri baseAddress = new Uri("http://localhost:8000/HelloService");
string address = "http://localhost:8000/HelloService/MyService";
using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), address);
serviceHost.Open();
Console.WriteLine("Press <enter> to terminate service");
Console.ReadLine();
serviceHost.Close();
}
다음 예제에서는 상대 주소("MyService")를 서비스 호스트의 기본 주소에 추가하는 방법을 보여 줍니다.
Uri baseAddress = new Uri("http://localhost:8000/HelloService");
using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), "MyService");
serviceHost.Open();
Console.WriteLine("Press <enter> to terminate service");
Console.ReadLine();
serviceHost.Close();
}
비고
서비스 애플리케이션의 ServiceDescription 속성은 OnOpening의 ServiceHostBase 메서드를 호출한 이후에 수정하면 안 됩니다.
Credentials 속성 및 AddServiceEndpoint
메서드와 같은 일부 멤버는 ServiceHostBase와 ServiceHost에서 해당 시점 이후에 수정된 경우 예외를 던집니다. 다른 것들은 수정이 가능하지만 결과는 불확실합니다.
마찬가지로 클라이언트에서 ServiceEndpoint 값을 OnOpening를 ChannelFactory에 호출한 후에는 변경해서는 안 됩니다. 해당 Credentials 지점 이후에 수정된 경우 속성이 예외를 throw합니다. 다른 클라이언트 설명 값은 오류 없이 수정할 수 있지만 결과는 정의되지 않습니다.
서비스 또는 클라이언트에 대해 호출 Open하기 전에 설명을 수정하는 것이 좋습니다.
기본 엔드포인트 사용
코드 또는 구성에 엔드포인트가 지정되지 않은 경우 런타임은 서비스에서 구현하는 각 서비스 계약의 각 기본 주소에 하나의 기본 엔드포인트를 추가하여 기본 엔드포인트를 제공합니다. 기본 주소는 코드 또는 구성에서 지정할 수 있으며, Open에서 ServiceHost이 호출될 때 기본 엔드포인트가 추가됩니다.
엔드포인트가 명시적으로 제공된 경우, AddDefaultEndpoints을 호출하기 전에 ServiceHost을 호출하여 기본 엔드포인트를 Open에 추가할 수 있습니다. 기본 엔드포인트, 바인딩 및 동작에 대한 자세한 내용은 단순화된 구성 및 WCF 서비스를 위한 단순화된 구성을 참조하세요.