Identificazione del client durante l’invocazione remota di .NET

Data questa class MarshalByRef:

public class MyRemotedClass : MarshalByRef { public void DoThis() { ... } public void DoThat() { ... } } 

Codice lato client:

 MyRemotedClass m = GetSomehowMyRemotedClass(); m.DoThis(); m.DoThat(); 

Posso avere diversi clienti che fanno la stessa cosa nello stesso momento. Vorrei distinguere i clienti. Come posso identificare all’interno dei metodi accessibili da remoto, da chi viene eseguita l’invocazione remota? Ad esempio, potrei registrare chi ha fatto cosa. (In realtà, non ho bisogno di rintracciare le informazioni del vero client, voglio solo essere in grado di raggruppare le invocazioni da parte dei clienti.)

[Modificato per aggiungere ulteriori informazioni di background]

Ho una quantità enorme di codice da coprire, comprese le proprietà. Pertanto l’estensione dell’elenco dei parametri di input non è un’opzione.

    Una delle cose che puoi fare è identificare un client per indirizzo IP implementando un IServerChannelSinkProvider .

    Aggiungi questa class al tuo progetto host remoto:

    ClientIPServerSinkProvider.cs

     using System; using System.Collections; using System.IO; using System.Runtime.Remoting; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Channels; using System.Threading; using System.Net; namespace MyRemotingEnvironment { public class ClientIPServerSinkProvider : IServerChannelSinkProvider { private IServerChannelSinkProvider _nextProvider = null; public ClientIPServerSinkProvider() { } public ClientIPServerSinkProvider( IDictionary properties, ICollection providerData) { } public IServerChannelSinkProvider Next { get { return _nextProvider; } set { _nextProvider = value; } } public IServerChannelSink CreateSink(IChannelReceiver channel) { IServerChannelSink nextSink = null; if (_nextProvider != null) { nextSink = _nextProvider.CreateSink(channel); } return new ClientIPServerSink(nextSink); } public void GetChannelData(IChannelDataStore channelData) { } } public class ClientIPServerSink : BaseChannelObjectWithProperties, IServerChannelSink, IChannelSinkBase { private IServerChannelSink _nextSink; public ClientIPServerSink(IServerChannelSink next) { _nextSink = next; } public IServerChannelSink NextChannelSink { get { return _nextSink; } set { _nextSink = value; } } public void AsyncProcessResponse( IServerResponseChannelSinkStack sinkStack, Object state, IMessage message, ITransportHeaders headers, Stream stream) { IPAddress ip = headers[CommonTransportKeys.IPAddress] as IPAddress; CallContext.SetData("ClientIPAddress", ip); sinkStack.AsyncProcessResponse(message, headers, stream); } public Stream GetResponseStream( IServerResponseChannelSinkStack sinkStack, Object state, IMessage message, ITransportHeaders headers) { return null; } public ServerProcessing ProcessMessage( IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream) { if (_nextSink != null) { IPAddress ip = requestHeaders[CommonTransportKeys.IPAddress] as IPAddress; CallContext.SetData("ClientIPAddress", ip); ServerProcessing spres = _nextSink.ProcessMessage( sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream); return spres; } else { responseMsg = null; responseHeaders = null; responseStream = null; return new ServerProcessing(); } } } } 

    Quindi, quando avvii il tuo host remoting fai qualcosa di simile al seguente:

     BinaryServerFormatterSinkProvider bp = new BinaryServerFormatterSinkProvider(); ClientIPServerSinkProvider csp = new ClientIPServerSinkProvider(); csp.Next = bp; Hashtable ht = new Hashtable(); ht.Add("port", "1234"); // Your remoting port number TcpChannel channel = new TcpChannel(ht, null, csp); ChannelServices.RegisterChannel(channel, false); RemotingConfiguration.RegisterWellKnownServiceType( typeof(MyRemotedClass), "MyRemotedClass.rem", WellKnownObjectMode.SingleCall); 

    Nel tuo metodo di chiamate puoi accedere all’indirizzo IP del client facendo:

     public class MyRemotedClass : MarshalByref { public void DoThis() { string clientIP = CallContext.GetData("ClientIPAddress").ToString(); } }