원격 서비스 예: CallContext
이 샘플에서는 CallContext 클래스와 ILogicalThreadAffinative 인터페이스를 사용하여 응용 프로그램 도메인 경계 또는 컨텍스트 경계를 넘는 호출의 양 끝에서 스레드 간에 데이터를 전달합니다.
이 응용 프로그램은 한 컴퓨터나 네트워크에서 실행됩니다. 이 응용 프로그램을 네트워크에서 실행하려면 클라이언트 구성의 **"localhost"**를 원격 컴퓨터의 이름으로 바꿔야 합니다.
이 샘플에서는 ServiceClass.vb를 컴파일하지 않지만 여기에서는 ILogicalThreadAffinative를 보여 주기 위해 ServiceClass.vb도 포함되어 있습니다.
경고
.NET Remoting에서는 기본적으로 인증이나 암호화를 수행하지 않습니다. 따라서 원격으로 클라이언트나 서버와 상호 작용하기 전에 클라이언트나 서버의 ID를 확인하는 데 필요한 모든 단계를 수행하는 것이 좋습니다. .NET Remoting 응용 프로그램을 실행하려면 FullTrust 권한이 필요하므로, 권한이 없는 클라이언트가 서버에 액세스할 수 있게 되면 해당 클라이언트는 완전히 신뢰받는 것처럼 코드를 실행할 수 있습니다. IIS(인터넷 정보 서비스)에서 원격화된 형식을 호스팅하거나 사용자 지정 채널 싱크 쌍을 만들어서 항상 끝점을 인증하고 통신 스트림을 암호화하십시오.
이 샘플을 컴파일하려면
명령 프롬프트에서 다음 명령을 입력합니다.
csc /r:System.Runtime.Remoting.dll /t:library ServiceClass.cs
csc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll client.cs
vbc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll clientvb.vb
csc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll server.cs
ServiceClass.cs
using System;
using System.Collections;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Channels;
public class ContextBoundType : ContextBoundObject{
private DateTime starttime;
public ContextBoundType(){
Console.WriteLine("A ContextBoundType instance has been created.");
starttime = DateTime.Now;
}
~ContextBoundType(){
Console.WriteLine("ContextBoundType being collected after " + (new TimeSpan(DateTime.Now.Ticks - starttime.Ticks)).ToString() + " seconds.");
}
public DateTime GetServerTime(){
Console.WriteLine("Time requested by a client.");
// This call overwrites the client's
// CallContextString.
CallContext.SetData("ServerThreadData", new CallContextString("This is the server side replacement."));
return DateTime.Now;
}
}
// One method of communicating between client and server is
// to use the CallContext. Calling CallContext essentially puts the data
// in a Thread Local Store. This means that the information is available
// to that thread or that "logical" thread (across application domains) only.
[Serializable]
public class CallContextString : ILogicalThreadAffinative{
String _str ="";
public CallContextString(String str){
_str = str;
Console.WriteLine("CallContextString created.");
}
public override String ToString(){
return _str;
}
}
ServiceClass.vb
이 파일은 설명용으로만 포함된 것입니다.
Imports System
Imports System.Collections
Imports System.Diagnostics
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Messaging
Imports System.Runtime.Remoting.Contexts
Imports System.Runtime.Remoting.Channels
Public Class ContextBoundType
Inherits ContextBoundObject
Private StartTime As DateTime
Public Sub New()
Console.WriteLine("A ContextBoundType instance has been created. (Constructor)")
StartTime = DateTime.Now
End Sub 'New
Protected Overrides Sub Finalize()
Console.WriteLine("ContextBoundType being collected after " & (New TimeSpan(DateTime.Now.Ticks - starttime.Ticks)).ToString() & " seconds.")
MyBase.Finalize()
End Sub 'Finalize
Public Function GetServerTime() As DateTime
Console.WriteLine("Time requested by a client.")
' This call overwrites the client's
' CallContextString.
CallContext.SetData("ServerThreadData", New CallContextString("This is the server side replacement."))
Return DateTime.Now
End Function 'GetServerTime
End Class 'ContextBoundType
' One of the methods of communicating between client and server is
' to use the CallContext. Calling CallContext essentially puts the data
' in a Thread Local Store. This means that the information is available
' to that thread or that "logical" thread (across application domains) only.
<Serializable> _
Public Class CallContextString
Implements ILogicalThreadAffinative
Private _str As String = ""
Public Sub New(ByVal Contents As String)
_str = Contents
Console.WriteLine("CallContextString created with string ""{0}""", Contents)
End Sub 'New
Public Overrides Function ToString() As String
Return _str
End Function 'ToString
End Class 'CallContextString
ClientVB.vb
Imports System
Imports System.Reflection
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports System.Runtime.Remoting.Channels.Http
Imports System.Runtime.Remoting.Contexts
Imports System.Runtime.Remoting.Messaging
Public Class ClientProcess
<MTAThread()> _
Public Shared Sub Main()
Dim Channel As New HttpChannel()
ChannelServices.RegisterChannel(Channel)
Dim RemoteType As New WellKnownClientTypeEntry(GetType(ContextBoundType), "https://localhost:8080/TcpCBOService")
RemotingConfiguration.RegisterWellKnownClientType(RemoteType)
' This sets a CallContextDataSlot on this thread. CallContextString
' will convert the ThreadLocalDataStore into a property on the
' message, which will then be merged into the ThreadLocalDataStore
' on the server. This is a nice way to pass information from client
' to server threads and back again. NOTE: This data store has
' logical thread scope. If an application domain has more than one
' thread making calls, each thread will have its own logical
' CallContext, and the server thread will keep each separate.
CallContext.SetData("ServerThreadData", New CallContextString("This is the thread data inserted on the client thread."))
Console.WriteLine("CallContextString prior to the call: " & CallContext.GetData("ServerThreadData").ToString())
Dim service As New ContextBoundType()
Console.WriteLine("Server time is: " & service.GetServerTime().ToLongTimeString())
Console.WriteLine("CallContextString after the call: " & CallContext.GetData("ServerThreadData").ToString())
End Sub 'Main
End Class 'ClientProcess
Client.cs
using System;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Messaging;
public class ClientProcess{
public static void Main(string[] Args){
HttpChannel channel = new HttpChannel();
ChannelServices.RegisterChannel(channel);
WellKnownClientTypeEntry remotetype = new WellKnownClientTypeEntry(typeof(ContextBoundType),"https://localhost:8080/TcpCBOService");
RemotingConfiguration.RegisterWellKnownClientType(remotetype);
// This sets a CallContextDataSlot on this thread.
// CallContextString will convert the ThreadLocalDataStore into
// a property on the message, which will then be merged into the
// ThreadLocalDataStore on the server. This is a nice way to pass
// information from client to server threads and back again.
// NOTE: This data store has logical thread scope. If an
// application domain has more than one thread making calls,
// each thread will have its own logical CallContext, and the
// server thread will keep each separate.
CallContext.SetData("ServerThreadData", new CallContextString("This is the thread data inserted on the client thread."));
Console.WriteLine("CallContextString prior to the call: " + CallContext.GetData("ServerThreadData").ToString());
ContextBoundType service = new ContextBoundType();
Console.WriteLine("Server time is: " + service.GetServerTime().ToLongTimeString());
Console.WriteLine("CallContextString after the call: " + CallContext.GetData("ServerThreadData").ToString());
}
}
Server.cs
using System;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Messaging;
using System.Threading;
public class ServerProcess{
public static void Main(string[] Args){
HttpChannel channel = new HttpChannel(8080);
ChannelServices.RegisterChannel(channel);
WellKnownServiceTypeEntry WKSTE = new WellKnownServiceTypeEntry(typeof(ContextBoundType),"TcpCBOService", WellKnownObjectMode.SingleCall);
RemotingConfiguration.RegisterWellKnownServiceType(WKSTE);
Console.WriteLine("Press enter to stop this process.");
Console.ReadLine();
}
}
참고 항목
참조
CallContext
ILogicalThreadAffinative