【问题标题】:.Net Remoting uses only one connection ?.Net Remoting 只使用一个连接?
【发布时间】:2013-02-06 10:39:45
【问题描述】:

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

我在任何地方都找不到答案。

【问题讨论】:

  • 我认为这取决于正在使用的渠道,但为什么你在 2013 年编写远程代码?
  • @Damien_The_Unbeliever 他可能正在从事一个旧项目。你是什​​么意思它取决于渠道?渠道决定了?

标签: c# .net remoting connection


【解决方案1】:

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

让我们做一个实验,看看最常见的默认情况。 我们有 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);

}

我们刚刚提到了一个名为Factory的类。

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 个线程都已创建启动,但它们都在等待以下调用:

signal.WaitOne();

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

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

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

signal.Set();

这就是发生的事情:

1)我们启动server控制台应用,让它安静运行:

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

3) 我们启动 Mark Russinovich 的 Process Explorer 并使用它来发现进程列表中的 client 进程,同时我们打开它的属性窗口并选择 TCP/IP 选项卡:

4) 我们在 client 控制台应用程序中按任意键,然后.. TA DAA !! 您在Process Explorer 中获得很多 连接。 他们有一百个吗?有时是,有时不是。 这是一个连接池,这是肯定的。 在一段时间(5 到 10 秒)空闲后,它们会关闭,这是一件非常好的事情(因为 .NET Remoting 堆栈就是以这种方式实现的)。

我希望这个实验总体上回答了你的问题。

在更具体的情况下,从更严格的意义上说,您应该查看文档并阅读您可能在 .NET Remoting 应用程序中使用的各种渠道(那里有很多渠道,您在这里看到的内容)只是 Microsoft 官方提供的常规 TcpChannel,这取决于您的 .NET Remoting 配置的内容,取决于您是否在 IIS 中托管服务器等)。

【讨论】:

  • 这是一个绝对漂亮的答案。谢谢!
【解决方案2】:

网络连接数取决于您使用的远程处理通道。默认的 TcpChannel 打开的网络连接数与您的程序中在某一时间点尝试访问服务器的线程数一样多。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-29
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多