Exemple de communication à distance : CallContext
Cette rubrique est spécifique à la technologie héritée assurant la compatibilité descendante avec des applications existantes et n'est pas recommandée en cas de nouveau développement. Les applications distribuées doivent maintenant être développées à l'aide de Windows Communication Foundation (WCF)
Cet exemple utilise la classe CallContext et l'interface ILogicalThreadAffinative pour passer des données entre une application cliente de communication à distance et une application serveur de communication à distance.
Cette application peut s'exécuter sur un seul ordinateur ou sur un réseau. Pour exécuter cette application sur un réseau, remplacez « localhost » dans la configuration client par le nom de l'ordinateur distant.
Attention : |
---|
Par défaut, .NET Remoting ne procède ni à l'authentification ni au chiffrement. Par conséquent, il est recommandé que vous preniez toutes les mesures nécessaires à l'identification des clients et des serveurs avant d'interagir à distance avec eux. Comme les applications .NET Remoting requièrent des autorisations FullTrust pour s'exécuter, un client non autorisé pourrait exécuter du code comme s'il était d'un niveau de confiance suffisant s'il se voyait accorder l'accès à votre serveur. Veillez à toujours authentifier vos clients et à chiffrer les flux de données de communication. Pour plus d'informations, consultez Sécurité dans la communication à distance. |
Pour compiler cet exemple
À l'invite de commandes, tapez les commandes suivantes :
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();
}
}
}