다음을 통해 공유


서비스 Channel-Level 프로그래밍

이 항목에서는 System.ServiceModel.ServiceHost 및 관련 개체 모델을 사용하지 않고 WCF(Windows Communication Foundation) 서비스 애플리케이션을 작성하는 방법에 대해 설명합니다.

메시지 수신

메시지를 받고 처리할 준비가 되려면 다음 단계가 필요합니다.

  1. 바인딩을 만듭니다.

  2. 채널 수신기를 빌드합니다.

  3. 채널 수신기를 엽니다.

  4. 요청을 읽고 회신을 보냅니다.

  5. 모든 채널 개체를 닫습니다.

바인딩 만들기

메시지를 수신 대기하고 받는 첫 번째 단계는 바인딩을 만드는 것입니다. WCF는 그 중 하나를 인스턴스화하여 직접 사용할 수 있는 몇 가지 기본 제공 또는 시스템 제공 바인딩과 함께 제공됩니다. 또한 목록 1의 코드에서 수행하는 CustomBinding 클래스를 인스턴스화하여 고유한 사용자 지정 바인딩을 만들 수도 있습니다.

아래 코드 예제에서는 System.ServiceModel.Channels.CustomBinding 인스턴스를 만들고 채널 스택을 빌드하는 데 사용되는 바인딩 요소의 컬렉션인 Elements 컬렉션에 System.ServiceModel.Channels.HttpTransportBindingElement 추가합니다. 이 예제에서는 요소 컬렉션에 HttpTransportBindingElement만 있으므로 결과 채널 스택에는 HTTP 전송 채널만 있습니다.

채널리스너 구축

바인딩을 만든 후 Binding.BuildChannelListener 호출하여 형식 매개 변수가 만들 채널 셰이프인 채널 수신기를 빌드합니다. 이 예제에서는 요청/회신 메시지 교환 패턴에서 들어오는 메시지를 수신 대기하려고 하기 때문에 System.ServiceModel.Channels.IReplyChannel 사용합니다.

IReplyChannel 요청 메시지를 수신하고 회신 메시지를 다시 보내는 데 사용됩니다. IReplyChannel.ReceiveRequest 호출하면 요청 메시지를 받고 회신 메시지를 다시 보내는 데 사용할 수 있는 System.ServiceModel.Channels.IRequestChannel반환됩니다.

수신기를 만들 때 수신 대기하는 네트워크 주소를 전달합니다. 이 경우 http://localhost:8080/channelapp. 일반적으로 각 전송 채널은 하나 또는 여러 주소 체계를 지원합니다. 예를 들어 HTTP 전송은 http 및 https 스키마를 모두 지원합니다.

또한 수신기를 만들 때 빈 System.ServiceModel.Channels.BindingParameterCollection 전달합니다. 바인딩 매개 변수는 수신기를 빌드하는 방법을 제어하는 매개 변수를 전달하는 메커니즘입니다. 이 예제에서는 이러한 매개 변수를 사용하지 않으므로 빈 컬렉션을 전달합니다.

들어오는 메시지 수신 대기

그런 다음 수신기에서 ICommunicationObject.Open 호출하고 채널 수락을 시작합니다. IChannelListener<TChannel>.AcceptChannel 동작은 전송이 연결 지향인지 아니면 연결이 없는지에 따라 달라집니다. 연결 지향 전송의 경우 AcceptChannel 새 연결 요청이 들어올 때까지 차단되며, 이때 새 연결을 나타내는 새 채널을 반환합니다. HTTP와 같은 연결 없는 전송의 경우 AcceptChannel 전송 수신기가 만드는 유일한 채널로 즉시 반환됩니다.

이 예제에서 수신기는 IReplyChannel구현하는 채널을 반환합니다. 이 채널에서 메시지를 받으려면 먼저 ICommunicationObject.Open 호출하여 통신 준비가 된 상태로 배치합니다. 그런 다음 메시지가 도착할 때까지 차단하는 ReceiveRequest 호출합니다.

요청 읽기 및 회신 보내기

ReceiveRequest RequestContext반환하면 RequestMessage 속성을 사용하여 받은 메시지를 받습니다. 메시지의 동작 및 본문 콘텐츠(문자열이라고 가정)를 작성합니다.

회신을 보내기 위해 이 경우 요청에서 받은 문자열 데이터를 다시 전달하는 새 회신 메시지를 만듭니다. 그런 다음 Reply 호출하여 회신 메시지를 보냅니다.

개체 닫기

리소스가 누출되지 않도록 하려면 더 이상 필요하지 않은 경우 통신에 사용되는 개체를 닫는 것이 매우 중요합니다. 이 예제에서는 요청 메시지, 요청 컨텍스트, 채널 및 수신기를 닫습니다.

다음 코드 예제에서는 채널 수신기가 하나의 메시지만 수신하는 기본 서비스를 보여 줍니다. 실제 서비스는 서비스가 종료될 때까지 채널을 수락하고 메시지를 계속 받습니다.

using System;
using System.ServiceModel.Channels;
namespace ProgrammingChannels
{
class Service
{
static void RunService()
{
    //Step1: Create a custom binding with just TCP.
    BindingElement[] bindingElements = new BindingElement[2];
    bindingElements[0] = new TextMessageEncodingBindingElement();
    bindingElements[1] = new HttpTransportBindingElement();

    CustomBinding binding = new CustomBinding(bindingElements);

    //Step2: Use the binding to build the channel listener.
    IChannelListener<IReplyChannel> listener =
          binding.BuildChannelListener<IReplyChannel>(
             new Uri("http://localhost:8080/channelapp"),
           new BindingParameterCollection());

    //Step3: Listening for messages.
    listener.Open();
    Console.WriteLine(
           "Listening for incoming channel connections");
    //Wait for and accept incoming connections.
    IReplyChannel channel = listener.AcceptChannel();
    Console.WriteLine("Channel accepted. Listening for messages");
    //Open the accepted channel.
    channel.Open();
    //Wait for and receive a message from the channel.
    RequestContext request= channel.ReceiveRequest();
    //Step4: Reading the request message.
    Message message = request.RequestMessage;
    Console.WriteLine("Message received");
    Console.WriteLine($"Message action: {message.Headers.Action}");
    string data=message.GetBody<string>();
    Console.WriteLine($"Message content: {data}");
    //Send a reply.
    Message replymessage=Message.CreateMessage(
        binding.MessageVersion,
        "http://contoso.com/someotheraction",
         data);
    request.Reply(replymessage);
    //Step5: Closing objects.
    //Do not forget to close the message.
    message.Close();
    //Do not forget to close RequestContext.
    request.Close();
    //Do not forget to close channels.
    channel.Close();
    //Do not forget to close listeners.
    listener.Close();
}
public static void Main()
{
    Service.RunService();
    Console.WriteLine("Press enter to exit");
    Console.ReadLine();
}
}
}
Imports System.ServiceModel.Channels

Namespace ProgrammingChannels
    Friend Class Service

        Private Shared Sub RunService()

            'Step1: Create a custom binding with just TCP.
            Dim bindingElements(1) As BindingElement = {New TextMessageEncodingBindingElement(), _
                                                        New HttpTransportBindingElement()}

            Dim binding As New CustomBinding(bindingElements)

            'Step2: Use the binding to build the channel listener.         
            Dim listener = binding.BuildChannelListener(Of IReplyChannel)(New Uri("http://localhost:8080/channelapp"), _
                                                                          New BindingParameterCollection())

            'Step3: Listening for messages.
            listener.Open()
            Console.WriteLine("Listening for incoming channel connections")

            'Wait for and accept incoming connections.
            Dim channel = listener.AcceptChannel()
            Console.WriteLine("Channel accepted. Listening for messages")

            'Open the accepted channel.
            channel.Open()

            'Wait for and receive a message from the channel.
            Dim request = channel.ReceiveRequest()

            'Step4: Reading the request message.
            Dim message = request.RequestMessage
            Console.WriteLine("Message received")
            Console.WriteLine("Message action: {0}", message.Headers.Action)
            Dim data = message.GetBody(Of String)()
            Console.WriteLine("Message content: {0}", data)
            'Send a reply.
            Dim replymessage = Message.CreateMessage(binding.MessageVersion, _
                                                     "http://contoso.com/someotheraction", data)
            request.Reply(replymessage)
            'Step5: Closing objects.
            'Do not forget to close the message.
            message.Close()
            'Do not forget to close RequestContext.
            request.Close()
            'Do not forget to close channels.
            channel.Close()
            'Do not forget to close listeners.
            listener.Close()
        End Sub

        Public Shared Sub Main()

            Service.RunService()
            Console.WriteLine("Press enter to exit")
            Console.ReadLine()

        End Sub

    End Class
End Namespace