.Net Remoting只使用一个连接?

时间:2013-02-21 07:19:22

标签: c# .net remoting connection

.Net Remoting是打开多个连接还是只打开一个连接? 假设我有一台服务器和一台客户端。如果客户端创建多个SingleCall对象。那么对于每个对象,是否会有一个新的连接,或者每个对象都会有一个连接?

我无法在任何地方找到答案。

2 个答案:

答案 0 :(得分:8)

答案很长:这取决于很多事情。 简短的回答是肯定的。是的。

让我们进行一项实验,看看最常见的默认情况。 我们有2个控制台应用程序和1个通用类库,由两个控制台应用程序引用。 第一个控制台应用程序具有客户端的角色,第二个控制台应用程序具有服务器的角色。

首先,这是通常依赖于类库的内容:

public interface IFactory {

    string Hello(string name);

}

现在提供一些服务器代码。这是启动:

private static TcpChannel channel;

static void Main(string[] args) {

  BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();
  BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
  serverProv.TypeFilterLevel = TypeFilterLevel.Full;

  channel = new TcpChannel(
    properties: new Hashtable {
      { @"port", 2013 }
    },
    clientSinkProvider: clientProv,
    serverSinkProvider: serverProv
  );
  ChannelServices.RegisterChannel(channel, false);
  RemotingConfiguration.RegisterWellKnownServiceType(typeof(Factory), "Factory.rem", WellKnownObjectMode.SingleCall);

  Console.WriteLine("Server started...");
  Console.WriteLine("Press any key to stop...");
  Console.ReadKey(intercept: true);

}

我们刚刚提到了一个名为工厂的课程。

RemotingConfiguration.RegisterWellKnownServiceType(typeof(Factory), "Factory.rem", WellKnownObjectMode.SingleCall);
你猜对了。这是 IFactory 实施:

private sealed class Factory : MarshalByRefObject, IFactory {

  #region IFactory Members

  string IFactory.Hello(string name) {
    return @"Hello " + name + @" !";
  }

  #endregion

}

现在有些客户:

static void Main(string[] args) {

  Console.WriteLine("Press any key to connect...");
  Console.ReadKey(intercept: true);

  IFactory factory = Activator.GetObject(typeof(IFactory), @"tcp://127.0.0.1:2013/Factory.rem") as IFactory;

  EventWaitHandle signal = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset);

  ThreadStart action = () => {

    signal.WaitOne();
    var result = factory.Hello("Eduard");
    Console.WriteLine(result);

  };

  foreach (var i in Enumerable.Range(0, 99))
    new Thread(action) { IsBackground = true }.Start();

  Console.WriteLine("Press any key to bombard server...");
  Console.ReadKey(intercept: true);

  signal.Set();


  Console.ReadKey(intercept: true);
}

你已经知道所有这些事情,我敢肯定。我们在另一侧获得了SingleCall服务的透明代理(它们都在同一台机器上,我们使用的是TCP端口2013):

IFactory factory = Activator.GetObject(typeof(IFactory), @"tcp://127.0.0.1:2013/Factory.rem") as IFactory;

然后,出于“同时性”的原因,我们创建了100个线程,启动它们(这可能需要一些时间),但是“用皮带保持它们”(信号是操作系统同步的必要手段)直到我们“扣动扳机”:

EventWaitHandle signal = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset);

ThreadStart action = () => {

  signal.WaitOne();
  var result = factory.Hello("Eduard");
  Console.WriteLine(result);

};

foreach (var i in Enumerable.Range(0, 99))
  new Thread(action) { IsBackground = true }.Start();

因此虽然已经创建了所有100个线程 AND ,但它们都在等待以下调用:

signal.WaitOne();

这样我们可以同时启动更好,否则线程本身的创建和启动会使它们的实际执行或多或少顺序。

我们要求用户决定何时用100个Hello调用“轰炸服务器”:

Console.WriteLine("Press any key to bombard server...");
Console.ReadKey(intercept: true);

signal.Set();

这就是发生的事情:

1)我们启动服务器控制台应用程序并让它平稳运行:

enter image description here

2)我们启动客户端控制台应用程序,通过按任意键“建立连接”(这只是一个逻辑连接,因为它只是创建一个透明的代理)但我们推迟了“轰炸” :

enter image description here

3)我们启动Mark Russinovich的Process Explorer并使用它来发现进程列表中的客户端进程,并在执行此操作时打开它的属性窗口并选择TCP / IP标签:

enter image description here

4)我们点击了客户端控制台应用中的任意一个键,然后.. TA DAA !! 您在Process Explorer中获得很多的关联。 他们是百?有时是,有时没有。 这是一个连接池,这是肯定的。 经过一段时间(5到10秒)的闲置后,他们关闭了,这是一件非常好的事情(因为.NET Remoting堆栈是以这种方式实现的)。

enter image description here

我希望这个实验能够回答你的问题。

在更具体的情况下,在更严格的意义上,您应该查看文档并阅读您可能在.NET Remoting应用程序中使用的各种渠道(其中有大量的通道,您在此处看到的内容)只是Microsoft正式提供的常规TcpChannel,它取决于您的.NET Remoting配置所说的,无论您是否在IIS中托管服务器等。)

答案 1 :(得分:0)

网络连接数取决于您使用的远程通道。默认的TcpChannel打开尽可能多的网络连接,因为程序中的许多线程试图在一个时间点访问服务器。

对于单线程应用程序,TcpChannel使用一个网络连接。

作为相反的示例,第三方远程通道IiopChannel使用多路复用,因此允许为数百个活动线程提供少量网络连接。