Question

Nous ayant un problème étrange avec .NET Remoting. Fondamentalement, nous avons un serveur qui enregistre deux TcpChannels avec ChannelServices.RegisterChannel():

  1. Une écoute sur le port 50000
  2. autre écoute sur le port 15000.

Nous avons alors un client qui enregistre un TcpChannel pour être en mesure de communiquer avec le serveur. Nous récupérons un objet à partir du serveur en appelant Activator.GetObject() avec l'URI

  

"tcp: // serverip: 50000 / objectname"

et ce beau des travaux, le client se connecte au serveur sur le port et obtient l'50000 objet.

Cependant, quand nous commençons à appeler des méthodes sur cet objet, la connexion au canal sur le port est tombé 50000, et une nouvelle connexion est faite au canal sur le port 15000 automatiquement. Cela pose un vrai problème pour nous, car nous ne voulons pas le trafic sur le port 15000 parce que le canal ne peut pas être lié à la même carte réseau que le port 50000 canal sur le serveur ou que le port ne peut pas être ouvert dans le pare-feu, ce qui provoque les appels d'accès distant à l'échec naturellement.

Ceci est très étrange pour nous puisque le client n'a pas connaissance dans notre code qu'il existe un autre canal sur le serveur ou sur le port 15000 IP ce qu'il écoute sur, mais il tente de s'y connecter.

Toute aide à ce sujet est très apprécié,

Merci, Casper

Ceci est le code qui met en place l'un des canaux de serveur, celui habituellement sur le port 50000:

IDictionary props = new Hashtable();

props["port"] = m_tcpPort;
props["name"] = String.Empty;


BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();

m_tcpChannel = new TcpServerChannel( props, /*clientProvider,*/ serverProvider );
ChannelServices.RegisterChannel( m_tcpChannel, false );

m_wellKnownObjRef = RemotingServices.Marshal( this, "Server@" + m_tcpPort.ToString() );

Ceci est le code qui met en place l'autre canal de serveur, généralement sur le port 15000:

IDictionary props = new Hashtable();

props["name"] = String.Empty;
props["port"] = ip.Port;
props["bindTo"] = ip.Address.ToString();                    
props["timeout"] = REMOTING_TIMEOUT; // Timeout to prevent hung remoting calls.

if (!String.IsNullOrEmpty( machineName ))
{
    props["machineName"] = machineName;
}

    BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
    serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

    BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();

    m_channel = new TcpChannel( props, clientProvider, serverProvider );
    ChannelServices.RegisterChannel( m_channel, false );

    m_objRef = RemotingServices.Marshal( this, QueueName ); // Queuename is a GUID.

Ceci est le code dans le client qui se connecte au premier canal du serveur, celui qui est habituellement sur le port 50000:

IDictionary props = new Hashtable();

props["port"] = 0;

RemotingConfiguration.CustomErrorsMode = CustomErrorsModes.Off;

BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();

m_tcpChannel = new TcpClientChannel(props, clientProvider/*, serverProvider*/);
ChannelServices.RegisterChannel(m_tcpChannel, false );

string address = "tcp://" + profile.RemoteIP + ":" + profile.RemoteTCP;

m_server = (Kernel)Activator.GetObject(typeof(Server), address + "/Server@" + port);
Était-ce utile?

La solution

Nous avons connecté un cas de support avec Microsoft à ce sujet et apparemment, ce que nous faisons ici est pas pris en charge par .NET Remoting. Vous êtes seulement autorisé à enregistrer un canal de chaque type dans un AppDomain. Qu'est-ce que Remoting fait est qu'il renvoie l'URI de l'objet au client pour lui dire où il peut accéder à l'objet en question. Quand il le fait, il regarde à travers les canaux enregistrés à la fin du serveur et utilise le premier canal qu'il y trouve qui correspond au type demandé (dans notre cas: Tcp). En d'autres termes, il utilisera quelque soit le canal arrive à se faire enregistrer en premier. Il ne se soucie pas du tout sur ce canal que le client a connecté sur.

La solution consiste à mettre en œuvre votre propre IClientChannelSinkProvider du côté client. Lorsque vous implémentez la méthode CreateSink (), vous pouvez choisir ce que vous voulez que le URL client de se connecter lors de la création de l'évier à utiliser.

Autres conseils

Je l'ai stuggle avec les "backlinked" ports ainsi; Je pensais que ce serait seulement occure si le serveur veut renvoyer quelque chose (même dans une procédure-événement). Parce que j'ai toujours eu des problèmes avec les pare-feu, je suis passé à GenuineChannels (bien que je pense que c'est un peu vieillot).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top