سؤال

نواجه مشكلة غريبة مع .NET Remoting. في الأساس ، لدينا خادم يسجل اثنين من القنوات ChannelServices.RegisterChannel():

  1. يستمع واحد على المنفذ 50000
  2. آخر يستمع على المنفذ 15000.

لدينا بعد ذلك عميل يسجل tcpchannel ليكون قادرًا على التواصل مع الخادم. نقوم باسترداد كائن من الخادم عن طريق الاتصال Activator.GetObject() مع URI

"TCP: // serverip: 50000/ObjectName"

وهذا يعمل بشكل جيد ، يتصل العميل بالخادم على المنفذ 50000 ويحصل على الكائن.

ومع ذلك ، عندما نبدأ في استدعاء أساليب هذا الكائن ، يتم إسقاط اتصال القناة على المنفذ 50000 ، ويتم إجراء اتصال جديد للقناة على المنفذ 15000 تلقائيًا. هذا يمثل مشكلة حقيقية بالنسبة لنا لأننا لا نريد حركة المرور على المنفذ 15000 لأن تلك القناة قد لا تكون مرتبطة بمحول الشبكة نفسه مثل قناة المنفذ 50000 على الخادم أو قد لا يكون هذا المنفذ مفتوحًا في جدار الحماية ، والذي يسبب مكالمات عن بعد للفشل بشكل طبيعي.

هذا غريب جدًا بالنسبة لنا نظرًا لأن العميل ليس لديه معرفة في الكود الخاص بنا ، حيث توجد قناة أخرى على الخادم على المنفذ 15000 أو ما الذي يستمع إليه ، ومع ذلك يحاول الاتصال به.

أي مساعدة في هذا موضع تقدير كبير،

شكرا ، كاسبر

هذا هو الرمز الذي يقوم بإعداد إحدى قنوات الخادم ، عادةً ما يكون على المنفذ 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() );

هذا هو الرمز الذي يقوم بإعداد قناة الخادم الأخرى ، عادة على المنفذ 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.

هذا هو الرمز في العميل الذي يتصل بقناة الخادم الأولى ، وهو عادة ما يكون على المنفذ 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);
هل كانت مفيدة؟

المحلول

لقد سجلنا حالة دعم مع Microsoft حول هذا الأمر ، ويبدو أن ما نفعله هنا لا يدعمه .NET Remoting. يُسمح لك فقط بتسجيل قناة واحدة من كل نوع في AppDomain واحد. ما يفعله جهاز التحكم عن بُعد هو أنه يعيد URI للكائن إلى العميل لإخباره أين يمكنه الوصول إلى الكائن المعني. عندما يفعل ذلك ، فإنه يبحث من خلال القنوات المسجلة في نهاية الخادم ويستخدم القناة الأولى التي تجدها هناك تتطابق مع النوع المطلوب (في حالتنا: TCP). وبعبارة أخرى ، سوف تستخدم أي قناة تحدث لتسجيلها أولاً. لا يهتم على الإطلاق بالما الذي تواصله العميل.

يتمثل الحل في تنفيذ iClientChannelsinkProvider الخاص بك على جانب العميل. عند تنفيذ طريقة CreateSink () ، يمكنك اختيار عنوان URL الذي تريد أن يتصل به العميل عند إنشاء الحوض لاستخدامه.

نصائح أخرى

لقد فعلت ذلك مع تلك المنافذ "المرتبطة" أيضًا ؛ اعتقدت أنه لن يحدث إلا إذا أراد الخادم إرسال شيء ما (حتى في عملية إعادة الحدث). لأنني كنت دائماً أمتلك مشاكل مع جدران الحماية ، فقد تحولت إلى قنوات Genuinechannels (على الرغم من أنني أعتقد أن هذا قديم بعض الشيء).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top