Remotingbeispiel: CallContext
Dieses Thema bezieht sich auf eine veraltete Technologie, die zum Zwecke der Abwärtskompatibilität mit vorhandenen Anwendungen beibehalten wird und nicht für die neue Entwicklung empfohlen wird. Verteilte Anwendungen sollten jetzt mit Windows Communication Foundation (WCF) entwickelt werden.
In diesem Beispiel werden die CallContext-Klasse und die ILogicalThreadAffinative-Schnittstelle verwendet, um Daten zwischen einer Remoteclientanwendung und einer Remoteserveranwendung zu übergeben.
Diese Anwendung wird auf einem einzelnen Computer oder über ein Netzwerk ausgeführt. Wenn Sie diese Anwendung über ein Netzwerk ausführen möchten, müssen Sie "localhost" in der Clientkonfiguration durch den Namen des Remotecomputers ersetzen.
Vorsicht: |
---|
.NET-Remoting führt standardmäßig keine Authentifizierung oder Verschlüsselung durch. Daher empfiehlt es sich, vor der Remoteinteraktion mit Clients und Servern alle erforderlichen Schritte zu unternehmen, um die Identität der Clients oder Server sicherzustellen. Da .NET-Remoteanwendungen FullTrust-Berechtigungen zur Ausführung benötigen, könnte ein nicht autorisierter Client Code so ausführen, als ob er voll vertrauenswürdig wäre, wenn dem Client Zugriff auf Ihren Server gewährt würde. Authentifizieren Sie die Clients unbedingt, und verschlüsseln Sie die Kommunikationsstreams. Weitere Informationen finden Sie unter Sicherheit beim Remoting. |
So kompilieren Sie dieses Beispiel
Geben Sie an der Eingabeaufforderung folgende Befehle ein:
vbc /r:System.Runtime.Remoting.dll /t:library MyRemoteType.vb vbc /r:System.Runtime.Remoting.dll /r:MyRemoteType.dll client.vb vbc /r:System.Runtime.Remoting.dll /r:MyRemoteType.dll server.vb
csc /r:System.Runtime.Remoting.dll /t:library MyRemoteType.cs csc /r:System.Runtime.Remoting.dll /r:MyRemoteType.dll client.cs csc /r:System.Runtime.Remoting.dll /r:MyRemoteType.dll server.cs
MyRemoteType
Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Messaging
Namespace [Shared]
Public Class MyRemoteType
Inherits MarshalByRefObject
Private starttime As DateTime
Public Sub New()
Console.WriteLine("A MyRemoteObject instance has been created.")
starttime = DateTime.Now
End Sub
Protected Overrides Sub Finalize()
Console.WriteLine("MyRemoteObject being collected after " & (New TimeSpan(DateTime.Now.Ticks - starttime.Ticks)).ToString() & " seconds.")
End Sub
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
End Class
' One method of communicating between client and server is
' to use the CallContext. Calling CallContext.SetData 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
Dim _str As String = ""
Public Sub New(ByVal str As String)
_str = str
Console.WriteLine("CallContextString created.")
End Sub
Public Overrides Function ToString() As String
Return _str
End Function
End Class
End Namespace
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
namespace Shared
{
public class MyRemoteType : MarshalByRefObject
{
private DateTime starttime;
public MyRemoteType()
{
Console.WriteLine("A MyRemoteObject instance has been created.");
starttime = DateTime.Now;
}
~MyRemoteType()
{
Console.WriteLine("MyRemoteObject 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.SetData 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;
}
}
}
Client
Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http
Imports System.Runtime.Remoting.Contexts
Imports System.Runtime.Remoting.Messaging
Imports [Shared]
Public Class Client
Public Shared Sub Main()
' Register Channel
Dim channel As HttpChannel = New HttpChannel()
ChannelServices.RegisterChannel(channel, False)
' Register MyRemoteObject
RemotingConfiguration.RegisterWellKnownClientType( _
GetType(MyRemoteType), _
"https://localhost:8080/MyRemoteObject")
' Add a CallContextString object to the call context
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 MyRemoteType = New MyRemoteType()
Console.WriteLine("Server time is: " & service.GetServerTime().ToLongTimeString())
Console.WriteLine("CallContextString after the call: " & CallContext.GetData("ServerThreadData").ToString())
End Sub
End Class
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Messaging;
using Shared;
namespace Client
{
public class Client
{
public static void Main(string[] args)
{
// Register Channel
HttpChannel channel = new HttpChannel();
ChannelServices.RegisterChannel(channel, false);
// Register MyRemoteObject
RemotingConfiguration.RegisterWellKnownClientType(
typeof(MyRemoteType),
"https://localhost:8080/MyRemoteObject");
// Add a CallContextString object to the call context
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());
MyRemoteType service = new MyRemoteType();
Console.WriteLine("Server time is: " + service.GetServerTime().ToLongTimeString());
Console.WriteLine("CallContextString after the call: " + CallContext.GetData("ServerThreadData").ToString());
}
}
}
Server
Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http
Imports [Shared]
Public Class Server
Public Shared Sub Main()
' Register channel
Dim channel As HttpChannel = New HttpChannel(8080)
ChannelServices.RegisterChannel(channel, False)
' Register MyRemoteObject
RemotingConfiguration.RegisterWellKnownServiceType( _
GetType(MyRemoteType), _
"MyRemoteObject", _
WellKnownObjectMode.SingleCall)
Console.WriteLine("Press enter to stop this process.")
Console.ReadLine()
End Sub
End Class
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using Shared;
namespace Server
{
class Server
{
static void Main(string[] args)
{
// Register channel
HttpChannel channel = new HttpChannel(8080);
ChannelServices.RegisterChannel(channel, false);
// Register MyRemoteObject
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(MyRemoteType),
"MyRemoteObject",
WellKnownObjectMode.SingleCall);
Console.WriteLine("Press enter to stop this process.");
Console.ReadLine();
}
}
}