Ejemplo de comunicación remota: CallContext
Este tema es específico de una tecnología heredada que se mantiene para la compatibilidad con versiones anteriores con aplicaciones existentes y no se recomienda para nuevo desarrollo. Las aplicaciones distribuidas se deberían desarrollar utilizando Windows Communication Foundation (WCF).
Este ejemplo utiliza la clase CallContext y la interfaz ILogicalThreadAffinative para pasar los datos entre una aplicación de cliente remoto y una aplicación de servidor remoto.
Esta aplicación se ejecuta en un solo equipo o a través de una red. Si desea ejecutar esta aplicación a través de una red, debe reemplazar “host local” en la configuración del cliente por el nombre del equipo remoto.
Precaución: |
---|
.NET Remoting no lleva a cabo la autenticación o el cifrado de forma predeterminada. Por consiguiente, se recomienda que dé todos los pasos necesarios para asegurarse de la identidad de los clientes o de los servidores antes de interactuar de forma remota con ellos. Dado que las aplicaciones de .NET Remoting exigen permisos FullTrust para ejecutarse, si a un cliente no autorizado se le permitiera el acceso a su servidor, el cliente podría ejecutar el código como si fuese un cliente de plena confianza. Autentique siempre a sus clientes y cifre las secuencias de comunicación. Para obtener más información, vea Seguridad en comunicación remota. |
Para compilar este ejemplo
Escriba los siguientes comandos en el símbolo del sistema:
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();
}
}
}