none
Remoting 获取远程对象返回结果判断 RRS feed

  • 问题

  • _manager = (IMainServiceManager)Activator.GetObject(typeof(IMainServiceManager), "tcp://" + ip + ":" + port.ToString() + "/IMainServiceManager");

    不管怎样——manager都不为空 ,如果我服务端没开启的话 结果也不为空 但是我在调用的时候 却报出“由于目标机器积极拒绝,无法连接。”的错误。

    现在我要怎么判断 -manager是否获取成功

    2011年4月18日 7:13

答案

  • 由于远程对象会被自动创建 Proxy 类,所以无论如何,Activator.GetObject 会得到非空对象。还有,GetObject 的行为会因为远程对象的不同而可能不同,比如是否是 MarshalByRef 或者 ByValue。

    详细情况可以参考 MSDN 的 Activator 帮助文档。


    Mark Zhou
    2011年4月18日 10:22
  • 谢谢了。但是还有个问题请教下。

    Server:

     

     

    class ServerProvide
    
      {
    
        BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
    
    
    
        BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
    
    
    
        IDictionary properties = new Hashtable();
    
    
    
        ObjRef objRefWellKnow;
    
    
    
        MainServiceManager MServiceManager = new MainServiceManager();
    
    
    
        public ServerProvide( )
    
        {
    
          
    
          serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
    
          properties["port"] = 9899;
    
    
    
        }
    
    
    
        public void Start()
    
        {
    
          TcpChannel tcpChannel = new TcpChannel(properties, clientProvider, serverProvider);//tcp通道
    
          ChannelServices.RegisterChannel(tcpChannel, true);
    
          objRefWellKnow = RemotingServices.Marshal(MServiceManager, "IMainServiceManager");
    
        }}
    

     

    Client:

     public class RemotingProvide
      {
    
        static RemotingProvide _remotingProvide;
        static object _Key = new object();
        BinaryServerFormatterSinkProvider serverProvider;
        BinaryClientFormatterSinkProvider clientProvider;
        IDictionary props ;
        TcpChannel tcpChannelMainService;
        int port = 9820;
        private RemotingProvide()
        {
          //使用TCP通道得到远程对象,不用监听
          serverProvider = new BinaryServerFormatterSinkProvider();
          clientProvider = new BinaryClientFormatterSinkProvider();
          serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
          props = new Hashtable();
    
          XX:
          props["port"] = port;
          props["name"] = "IMService";
          try
          {
            tcpChannelMainService = new TcpChannel(props, clientProvider, serverProvider);
            
          }
          catch 
          {
            port++;
            goto XX;
          }
          ChannelServices.RegisterChannel(tcpChannelMainService, true);
        }
    
        public static RemotingProvide GetInstance()
        {
          if (_remotingProvide == null)
          {
            lock (_Key)
            {
              if (_remotingProvide == null)
              {
    
                _remotingProvide = new RemotingProvide();
              }
            }
          }
          return _remotingProvide;
        }
    
        public IMainServiceManager GetRemotMainServiceManager(string ip, int port)
        {
    
          IMainServiceManager _manager=null;
         
          _manager = (IMainServiceManager)Activator.GetObject(typeof(IMainServiceManager), "tcp://" + ip + ":" + port.ToString() + "/IMainServiceManager");
          
          
          return _manager;
        }
    
        
      }
    

    这个是我服务端和客户端类似的代码,因为我服务端已启动就有MainServiceManager 对象存在,执行相关的业务功能。

    客户端是一个管理界面,客户端主要是为了操作管理服务端的MainServiceManager对象。如果客户端管理界面存在,MainServiceManager的一些运行信息和日志会通过事件

    告知客户端。

    但是现在主要的问题是:客户端执行远程对象的一些操作后,过一会儿,远程对象会被回收。如果使用租约的话但是有只能适用于客户端激活和SingleCall.

    怎么才能解决我这种情况的续约。


     

    2011年5月10日 9:01
  • 有两种方法您可以不妨一试。第一,在服务器上,用 GC.KeepAlive 把需要保留的未包装对象标记成不回收。二,在客户端采用 PerCall 的方式,每次调用远程对象时创建新的包装类实例。

    这两种方法各有优缺点。比如,GC.KeepAlive 会导致托管堆上的死角,它会影响 GC 在 Compact 过程中性能,PerCall 的话通信成本很高,每次都会重新建立 TCP 连接。如果您需要 TCP 长连接的话,我建议您可以采用 WCF Service,它提供的 ChallelFactory 是带缓存的,不会导致远程对象回收问题。


    Mark Zhou
    2011年5月10日 9:54
  • 再次感谢,呵呵。

    还想问下呵呵。

     TcpChannel tcpChannelMainService = new TcpChannel(props, clientProvider, serverProvider);
    
    是不是在同一AppDomain里面只能创建一个。

    2011年5月16日 2:04
  • 这个我就不大清楚了。因为 TcpChannel 从本质上应该占用一个本地端口的,这个可能与 AppDomain 没什么关系。您可以试试。
    Mark Zhou
    2011年5月16日 6:50

全部回复

  • 由于远程对象会被自动创建 Proxy 类,所以无论如何,Activator.GetObject 会得到非空对象。还有,GetObject 的行为会因为远程对象的不同而可能不同,比如是否是 MarshalByRef 或者 ByValue。

    详细情况可以参考 MSDN 的 Activator 帮助文档。


    Mark Zhou
    2011年4月18日 10:22
  • 谢谢了。但是还有个问题请教下。

    Server:

     

     

    class ServerProvide
    
      {
    
        BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
    
    
    
        BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
    
    
    
        IDictionary properties = new Hashtable();
    
    
    
        ObjRef objRefWellKnow;
    
    
    
        MainServiceManager MServiceManager = new MainServiceManager();
    
    
    
        public ServerProvide( )
    
        {
    
          
    
          serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
    
          properties["port"] = 9899;
    
    
    
        }
    
    
    
        public void Start()
    
        {
    
          TcpChannel tcpChannel = new TcpChannel(properties, clientProvider, serverProvider);//tcp通道
    
          ChannelServices.RegisterChannel(tcpChannel, true);
    
          objRefWellKnow = RemotingServices.Marshal(MServiceManager, "IMainServiceManager");
    
        }}
    

     

    Client:

     public class RemotingProvide
      {
    
        static RemotingProvide _remotingProvide;
        static object _Key = new object();
        BinaryServerFormatterSinkProvider serverProvider;
        BinaryClientFormatterSinkProvider clientProvider;
        IDictionary props ;
        TcpChannel tcpChannelMainService;
        int port = 9820;
        private RemotingProvide()
        {
          //使用TCP通道得到远程对象,不用监听
          serverProvider = new BinaryServerFormatterSinkProvider();
          clientProvider = new BinaryClientFormatterSinkProvider();
          serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
          props = new Hashtable();
    
          XX:
          props["port"] = port;
          props["name"] = "IMService";
          try
          {
            tcpChannelMainService = new TcpChannel(props, clientProvider, serverProvider);
            
          }
          catch 
          {
            port++;
            goto XX;
          }
          ChannelServices.RegisterChannel(tcpChannelMainService, true);
        }
    
        public static RemotingProvide GetInstance()
        {
          if (_remotingProvide == null)
          {
            lock (_Key)
            {
              if (_remotingProvide == null)
              {
    
                _remotingProvide = new RemotingProvide();
              }
            }
          }
          return _remotingProvide;
        }
    
        public IMainServiceManager GetRemotMainServiceManager(string ip, int port)
        {
    
          IMainServiceManager _manager=null;
         
          _manager = (IMainServiceManager)Activator.GetObject(typeof(IMainServiceManager), "tcp://" + ip + ":" + port.ToString() + "/IMainServiceManager");
          
          
          return _manager;
        }
    
        
      }
    

    这个是我服务端和客户端类似的代码,因为我服务端已启动就有MainServiceManager 对象存在,执行相关的业务功能。

    客户端是一个管理界面,客户端主要是为了操作管理服务端的MainServiceManager对象。如果客户端管理界面存在,MainServiceManager的一些运行信息和日志会通过事件

    告知客户端。

    但是现在主要的问题是:客户端执行远程对象的一些操作后,过一会儿,远程对象会被回收。如果使用租约的话但是有只能适用于客户端激活和SingleCall.

    怎么才能解决我这种情况的续约。


     

    2011年5月10日 9:01
  • 有两种方法您可以不妨一试。第一,在服务器上,用 GC.KeepAlive 把需要保留的未包装对象标记成不回收。二,在客户端采用 PerCall 的方式,每次调用远程对象时创建新的包装类实例。

    这两种方法各有优缺点。比如,GC.KeepAlive 会导致托管堆上的死角,它会影响 GC 在 Compact 过程中性能,PerCall 的话通信成本很高,每次都会重新建立 TCP 连接。如果您需要 TCP 长连接的话,我建议您可以采用 WCF Service,它提供的 ChallelFactory 是带缓存的,不会导致远程对象回收问题。


    Mark Zhou
    2011年5月10日 9:54
  • 再次感谢,呵呵。

    还想问下呵呵。

     TcpChannel tcpChannelMainService = new TcpChannel(props, clientProvider, serverProvider);
    
    是不是在同一AppDomain里面只能创建一个。

    2011年5月16日 2:04
  • 这个我就不大清楚了。因为 TcpChannel 从本质上应该占用一个本地端口的,这个可能与 AppDomain 没什么关系。您可以试试。
    Mark Zhou
    2011年5月16日 6:50