2009-02-09 11 views
7

Data questa classe MarshalByRefObject: codice latoidentifica il cliente durante una chiamata .NET Remoting

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

Cliente:

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

posso avere diversi clienti a fare la stessa cosa alla stesso tempo. 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 risalire la vera informazioni cliente, voglio solo essere in grado di invocazioni di gruppo da parte dei clienti.)

[A cura di aggiungere ulteriori informazioni di sfondo]

ho un enorme quantità di codice coprire, comprese le proprietà. Pertanto l'estensione dell'elenco dei parametri di input non è un'opzione.

risposta

15

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

Aggiungere questa classe al progetto di accoglienza Remoting:

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(); 
      } 
     } 


    } 
} 

Poi, quando si avvia il host di comunicazione remota fare 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 metodo si chiama può accedere all'indirizzo IP del client eseguendo:

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

È davvero così complicato solo ottenere un indirizzo IP client? – IAbstract

+2

@dboarman: è l'unico modo. Ma se ti sei abituato a scrivere le tue classi di sink del canale, allora diventa una parte normale del remoting life. – Kev

+0

Sì, sfortunatamente per me questa è davvero la mia prima incursione in Remoting ... che sto mettendo da parte per ora. Non mi piace usare i servizi remoti quando potrei implementare la protobuf-net di Marc Gravell. Per ora sto andando in una direzione leggermente diversa ... grazie per il tuo aiuto, comunque. – IAbstract

Problemi correlati