싱크 및 싱크 체인

이 항목은 이전 버전의 기존 응용 프로그램과의 호환성을 위해 유지되고 있으나 새로운 개발에는 권장되지 않는 레거시 기술에 대해 설명합니다. 분산 응용 프로그램은 이제 WCF(Windows Communication Foundation)를 사용하여 개발됩니다.

클라이언트는 메시지를 원격 응용 프로그램 도메인으로 보내 원격 개체에서 메서드 호출을 수행합니다. 이 작업은 채널 개체 집합에 의해 수행됩니다. 클라이언트 응용 프로그램 도메인에는 클라이언트 채널이 포함되고 원격 응용 프로그램 도메인에는 원격 채널이 포함됩니다. 각 채널은 체인으로 연결된 일련의 채널 싱크로 구성됩니다. 다음 그림에서는 기본 채널 싱크 체인의 구조를 보여 줍니다.

싱크 및 싱크 체인

채널은 메시지를 보내기 전이나 받은 후에 채널 싱크 개체의 체인에 따라 각 메시지를 보냅니다. 이 싱크 체인에는 포맷터, 전송 또는 스택 빌더 싱크 같은 기본 채널 기능에 필요한 싱크가 포함되지만 채널 싱크 체인을 사용자 지정하여 메시지나 스트림과 관련된 특별한 작업을 수행할 수 있습니다. 각 채널 싱크는 IClientChannelSink 또는 IServerChannelSinkfrlrfSystemRuntimeRemotingChannelsIServerChannelSinkClassTopic를 구현합니다. 클라이언트의 첫 번째 채널 싱크는 IMessageSinkfrlrfSystemRuntimeRemotingMessagingIMessageSinkClassTopic도 구현해야 합니다. 일반적으로 IMessageSink, IChannelSinkBaseIClientChannelSink에서 모두 상속되는 IClientFormatterSink를 구현하며, 들어오는 메시지를 스트림(IMessagefrlrfSystemRuntimeRemotingMessagingIMessageClassTopic 개체)으로 변환하므로 포맷터 싱크라고 합니다.

채널 싱크 체인은 응용 프로그램 도메인과 주고 받은 모든 메시지를 처리합니다. 채널 싱크는 처리되는 메시지에 액세스할 수 있으며 후속 처리는 처리 후 시스템으로 반환된 메시지를 사용합니다. 기본적으로 채널 싱크에서 로깅 서비스나 모든 종류의 필터를 구현합니다.

각 채널 싱크는 스트림을 처리한 다음 이 스트림을 다음 채널 싱크로 전달하므로 특정 싱크 앞이나 뒤의 싱크가 전달된 스트림에 대해 수행할 작업을 알고 있어야 합니다.

tdzwhfy3.note(ko-kr,VS.100).gif참고:
메시지 싱크에서 예외를 throw하면 안 됩니다. 메시지 싱크에서 이를 제어하는 한 가지 방법으로 try-catch 블록에 메서드 코드를 래핑할 수 있습니다.

채널 싱크 공급자(IClientChannelSinkProviderfrlrfSystemRuntimeRemotingChannelsIClientChannelSinkProviderClassTopic, IClientFormatterSinkProviderfrlrfSystemRuntimeRemotingChannelsIClientFormatterSinkProviderClassTopic 또는 IServerChannelSinkProvider 인터페이스를 구현하는 개체)는 .NET Remoting 메시지를 처리하는 채널 싱크를 만듭니다. 원격 형식을 활성화하면 채널 싱크 공급자가 채널에서 검색되며 싱크 공급자에서 CreateSink 메서드를 호출하여 체인의 첫 번째 채널 싱크를 검색합니다.

채널 싱크는 클라이언트와 서버 간의 메시지 전송을 담당합니다. 또한 채널 싱크는 체인으로 연결됩니다. 싱크 공급자에서 CreateSink 메서드를 호출하면 다음을 수행해야 합니다.

  • 채널 싱크를 만듭니다.

  • 체인의 다음 싱크 공급자에서 CreateSink를 호출합니다.

  • 다음 싱크와 현재 싱크가 연결되는지 확인합니다.

  • 싱크를 호출자에게 반환합니다.

채널 싱크는 수행된 모든 호출을 체인의 다음 싱크로 전달하며 다음 싱크에 대한 참조를 저장할 메커니즘을 제공해야 합니다.

채널 싱크는 유연성 있게 싱크 체인 아래로 보낼 수 있습니다. 예를 들어 serialize된 원래 메시지를 보내기 전에 인증을 협상하는 보안 싱크는 전체 채널 메시지를 유지하고, 콘텐츠 스트림을 해당 콘텐츠로 바꾸고, 원격 응용 프로그램 도메인까지 싱크 체인 아래로 보낼 수 있습니다. 보안 싱크는 반환 과정에서 회신 메시지를 해석하고 원격 응용 프로그램 도메인의 해당 보안 싱크를 사용하여 대화를 만들 수 있습니다. 합의에 도달하면 원래 보안 싱크가 원래 콘텐츠 스트림을 원격 응용 프로그램 도메인으로 보낼 수 있습니다.

채널 싱크 체인의 메시지 처리

.NET Remoting 시스템이 메시지를 처리할 수 있는 채널을 찾으면 채널이

SyncProcessMessage(또는 AsyncProcessMessage)를 호출하여 메시지를 포맷터 채널 싱크로 전달합니다. 포맷터 싱크는 전송 헤더 배열을 만들고 다음 싱크에서 GetRequestStream을 호출합니다. 이 호출은 싱크 체인으로 전달되고 싱크는 포맷터 싱크로 다시 전달되는 요청 스트림을 만들 수 있습니다. GetRequestStream에서 null 참조(Visual Basic의 경우 Nothing)를 반환하면 포맷터 싱크가 serialization에 사용할 자체 싱크를 만듭니다. 이 호출이 반환되면 메시지가 serialize되고 싱크 체인의 첫 번째 채널 싱크에서 해당 메시지 처리 메서드가 호출됩니다.

싱크는 스트림에 데이터를 쓸 수 없지만 스트림을 읽거나 필요한 위치를 따라 새 스트림을 전달할 수 있습니다. 또한 싱크는 헤더 배열에 헤더를 추가하고(이전에 다음 싱크에서 GetRequestStream을 호출하지 않은 경우), 호출을 다음 싱크로 전달하기 전에 싱크 스택에 자신을 추가할 수 있습니다. 동기화 스택은 완료 시 비동기 호출이 호출자를 콜백할 수 있도록 하는 데 사용됩니다. 호출이 체인의 끝에 있는 전송 싱크에 도달하면 전송 싱크에서는 채널을 통해 헤더와 serialize된 메시지를 서버에 보냅니다. 이 메시지를 받은 서버에서는 전체 프로세스가 반대로 수행됩니다. 서버측의 전송 싱크는 스트림의 서버측에서 헤더와 serialize된 메시지를 검색하여 포맷터 싱크에 도달할 때까지 싱크 체인을 통해 전달합니다. 포맷터 싱크는 메시지를 deserialize하여 .NET Remoting 시스템으로 전달합니다. 여기서 메시지가 메서드 호출로 변경되어 서버 개체에서 호출됩니다.

채널 싱크 체인 만들기

새 채널 싱크를 만들려면 IServerChannelSinkProvider 또는 IClientChannelSinkProvider 구현을 인식하도록 .NET Remoting 시스템을 구현 및 구성해야 합니다. 이 구현에서 사용자 지정 IClientChannelSink 또는 IServerChannelSink 구현을 만들거나 체인의 다음 싱크를 검색할 수 있습니다. BaseChannelSinkWithProperties 추상 클래스를 사용하여 사용자 지정 채널 싱크를 구현할 수 있습니다.

채널 싱크 공급자 작성

응용 프로그램은 채널을 생성할 때 서버 또는 클라이언트 채널 싱크 공급자를 매개 변수로 제공할 수 있습니다. 채널 싱크 공급자는 체인에 저장되어야 하며, 개발자가 외부 공급자를 채널 생성자로 전달하기 전에 모든 채널 싱크 공급자를 연결해야 합니다. 채널 싱크 공급자는 이러한 용도로 Next 속성을 구현합니다. 다음 코드 예제에서는 클라이언트 채널 싱크 공급자를 작성하는 방법을 보여 줍니다. 원격 서비스 예제: 채널 싱크 공급자에서 전체 예제를 볼 수 있습니다.

private Function CreateDefaultClientProviderChain() As IClientChannelSinkProvider
   Dim chain As New FirstClientFormatterSinkProvider            
   Dim sink As IClientChannelSinkProvider
   sink = chain
   sink.Next = New SecondClientFormatterSinkProvider
   sink = sink.Next
   return chain
End Function 
private IClientChannelSinkProvider CreateDefaultClientProviderChain(){
   IClientChannelSinkProvider chain = new FirstClientFormatterSinkProvider();            
   IClientChannelSinkProvider sink = chain;
   sink.Next = new SecondClientFormatterSinkProvider();
   sink = sink.Next;
   return chain;
} 
tdzwhfy3.note(ko-kr,VS.100).gif참고:
하나의 구성 파일에 채널 싱크 공급자가 여러 개 제공된 경우 .NET Remoting 시스템은 채널 싱크 공급자를 해당 구성 파일에 있는 순서대로 연결합니다. Configure를 호출하는 동안 채널을 만들 때 채널 싱크 공급자도 만들어집니다.

포맷터 싱크

포맷터 싱크는 IMessage를 구현하는 개체로 채널 메시지를 메시지 스트림에 serialize합니다. 일부 포맷터 싱크 구현에서는 시스템 제공 포맷터 형식(BinaryFormatterfrlrfSystemRuntimeSerializationFormattersBinaryBinaryFormatterClassTopicSoapFormatterfrlrfSystemRuntimeSerializationFormattersSoapSoapFormatterClassTopic)을 사용합니다. 다른 일부 포맷터 싱크의 구현에서는 자체 수단을 사용하여 채널 메시지를 스트림으로 변환합니다.

포맷터 싱크는 필요한 헤더를 생성하고 스트림으로 메시지를 serialize하는 기능을 수행합니다. 포맷터가 싱크된 다음에는 SyncProcessMessage 또는 AsyncProcessMessage 호출을 통해 메시지가 싱크 체인의 모든 싱크로 전달됩니다. 이 단계에서는 메시지가 이미 serialize되었으며 수정할 수 없습니다.

tdzwhfy3.note(ko-kr,VS.100).gif참고:
메시지 자체를 만들거나 수정해야 하는 싱크는 싱크 체인에서 포맷터 앞에 배치되어야 합니다. IClientFormatterSink를 구현하여 포맷터 싱크에 대한 참조가 있도록 시스템에 지정하면 쉽게 이 작업을 수행할 수 있습니다. 그런 다음 실제 포맷터 싱크를 싱크 체인에 배치합니다.

포맷터 싱크는 반환 과정에서 메시지 스트림을 채널 메시지 개체(반환 메시지)로 다시 변환합니다. 클라이언트의 첫 번째 싱크는 IClientFormatterSink 인터페이스를 구현해야 합니다. CreateSink가 채널에 반환될 때 반환되는 참조는 SyncProcessMessage 메서드를 호출할 수 있도록 IClientFormatterSink 형식으로 캐스팅됩니다. IClientFormatterSinkIMessageSink에서 파생됩니다. 캐스트가 실패하면 시스템에서 예외를 발생시킵니다.

사용자 지정 채널 싱크

클라이언트에서 사용자 지정 채널 싱크는 포맷터 싱크와 마지막 전송 싱크 사이의 개체 체인에 삽입됩니다. 클라이언트 또는 서버 채널에 사용자 지정 채널 싱크를 삽입하면 다음 지점 중 하나에서 IMessage를 처리할 수 있습니다.

  • 메시지로 표현된 호출을 스트림으로 변환하여 연결을 통해 보내는 프로세스 중

  • 스트림을 연결에서 해제하여 서버 원격 개체나 클라이언트 프록시 개체 앞의 마지막 메시지 싱크로 보내는 프로세스 중

사용자 지정 싱크는 호출이 나가는지, 들어오는지에 따라 데이터를 읽거나 스트림에 쓰고 필요한 경우 헤더에 정보를 추가할 수 있습니다. 이 단계에서는 포맷터가 메시지를 이미 serialize했으며 수정할 수 없습니다. 메시지 호출을 체인 끝의 전송 싱크로 전달하는 경우 전송 싱크에서 스트림에 헤더를 쓰고 채널에 표시된 전송 프로토콜을 사용하여 서버의 전송 싱크로 스트림을 전달합니다.

전송 싱크

전송 싱크는 클라이언트에 있는 체인의 마지막 싱크이고 서버에 있는 체인의 첫 번째 싱크입니다. serialize된 메시지 전송 외에도 전송 싱크는 헤더를 서버로 보내고 호출이 서버에서 반환될 때 헤더 및 스트림을 검색합니다. 이러한 싱크는 채널에 기본 제공되며 확장할 수 없습니다.

기본 포맷터 바꾸기

채널은 추상 네트워킹 메커니즘이므로 시스템에서 구현한 채널을 선택한 포맷터와 결합하도록 .NET Remoting 시스템을 구성할 수 있습니다. 채널 속성의 IDictionary 구현, 서버의 포맷터 및 클라이언트의 포맷터를 취하는 채널 생성자를 사용하여 이 작업을 수행할 수 있습니다. 구성 파일에 포맷터를 지정할 수도 있습니다. 다음 예제에서는 .NET Remoting 구성 시스템에 HttpChannel을 만들지만 클라이언트의 BinaryClientFormatterSink를 사용하도록 지정합니다.

<configuration>
   <system.runtime.remoting>
      <application>
         <channels>
            <channel ref="http">
               <clientProviders>
                  <formatter ref="binary"/>
               </clientProviders>
         <channels>
      </application>
   </system.runtime.remoting>
</configuration> 

다음 코드에서는 프로그래밍 방식으로 동일한 작업을 수행하며 GetServerStringGetServerTime을 구현하는 원격 인터페이스 형식 IService를 가정합니다.

Imports System
Imports System.Collections
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http

Public Class ClientProcess
  <MTAThread()> _
  Public Shared Sub Main()
      
    ' Note that any name/value pairs of configuration attributes can be 
    ' placed in this dictionary (the configuration system calls this same 
    ' constructor).
    Dim properties As New Hashtable()
    properties("name") = "HttpBinary"
     
    ChannelServices.RegisterChannel(New HttpChannel(properties, New BinaryClientFormatterSinkProvider(), Nothing))
    ' The last parameter above (Nothing) is the server sink provider chain 
    ' to obtain the default behavior (which includes SOAP and 
    ' binary formatters on the server side).
    Dim service As IService = CType(Activator.GetObject(GetType(IService), "http://computer:8080/SAService"), IService)
      
    Console.WriteLine("Server string is: " + service.GetServerString())
    Console.WriteLine("Server time is: " + service.GetServerTime())
  End Sub
   
End Class 
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;

public class ClientProcess{

  public static void Main(string[] Args){
        
    // Note that any name/value pairs of configuration attributes can be 
    // placed in this dictionary (the configuration system calls this 
    // same HttpChannel constructor).
    IDictionary properties = new Hashtable();
    properties["name"] = "HttpBinary";

    // The last parameter below is the server sink provider chain 
    // to obtain the default behavior (which includes SOAP and binary 
    // formatters) on the server side.
    ChannelServices.RegisterChannel(new HttpChannel(properties, new BinaryClientFormatterSinkProvider(), null));

    IService service = (IService)Activator.GetObject(typeof(IService),"http://computer:8080/SAService");
        
    Console.WriteLine("Server string is: " + service.GetServerString());
    Console.WriteLine("Server time is: " + service.GetServerTime());      
  }
}

IIS(인터넷 정보 서비스)에 호스팅된 이 채널 및 포맷터 조합의 전체 예는 원격 서비스 예제: IIS에서 호스팅을 참조하십시오.

SoapClientFormatterSink frlrfSystemRuntimeRemotingChannelsSoapClientFormatterSinkClassTopic 개체와 함께 TcpChannel 개체를 사용하도록 이 클라이언트를 변경하려면 다음 코드와 같이 네임스페이스와 RegisterChannel **** 호출만 변경해야 합니다.

ChannelServices.RegisterChannel(New TcpChannel(properties, New SoapClientFormatterSinkProvider(), Nothing))
ChannelServices.RegisterChannel(new TcpChannel(properties, new SoapClientFormatterSinkProvider(), null));

참고 항목

개념

IIS의 원격 개체 호스팅
원격 서비스 예제: IIS에서 호스팅

관련 자료

고급 원격 서비스