C#套接字与管道

目前我正在开发Windows上的多进程桌面应用程序。 此应用程序将是一个收缩包装的应用程序,它将部署在世界各地的客户端计算机上。 虽然我们可以对机器有广泛的规格 – 例如带有.Net 4.0 CF的Windows XP SP3,但我们无法控制它们,我们无法对其配置过于具体 – 例如我们无法指定机器必须具有cuda 1.4图形处理器等等

其中一些进程是托管的(.Net 4.0),其他进程是非托管的(C ++ Win32)。 这些流程需要共享数据。 我迄今评估的选项是

  • Tcp套接字
  • 命名管道

管道看起来好一点,但是对于我们的需求 – 两者的性能都是可以接受的。 套接字为我们提供了跨越机器(和操作系统 – 我们最终支持非Microsoft操作系统)边界的灵活性,因此我们倾向于使用套接字。

但是 – 我主要担心的是 – 如果我们使用Tcp套接字 – 我们是否可能遇到防火墙问题? 是否有其他人部署了使用TCP进行IPC和经历过问题的桌面应用程序/程序? 如果是这样 – 什么样的?

我知道这是一个相当开放的问题,我很乐意改写。 但我真的想知道我们可能会遇到什么样的潜在问题。

编辑:为了更轻松 – 我们只运送一些POD,整数,浮点数和字符串。 我们构建了一个抽象层,提供了两种范例 – 请求/响应和订阅。 传输层已被抽象出来,目前我们有两个实现 – 基于管道和基于TCP。

在快速LAN上管道的性能通常更好,但TCP在较慢的网络或WAN上通常更好。 请参阅下面的msdn点。

TPC更易于配置。 关于防火墙,它们允许您打开/关闭通信端口。 如果这不是一个选项或关注点,另一个选项是http(REST / json,web服务,xml rpc等等),但不确定http开销是否可接受。 确保你使用真实世界的数据集进行尝试(在测试中传递琐碎的数据会使开销看起来不合理 – 与现实世界的数据集相比,通常是次要的)。

来自msdn的其他一些信息:

在快速局域网(LAN)环境中,传输控制协议/ Internet协议(TCP / IP)套接字和命名管道客户端在性能方面具有可比性。 但是,TCP / IP套接字和命名管道客户端之间的性能差异在较慢的网络中变得明显,例如跨广域网(WAN)或拨号网络。 这是因为进程间通信(IPC)机制在对等体之间进行通信的方式不同。

对于命名管道,网络通信通常更具交互性。 对等体不会发送数据,直到另一个对等体使用读取命令请求它。 网络读取通常涉及一系列查看管道消息,然后才开始读取数据。 这在慢速网络中可能非常昂贵并且导致过多的网络流量,这反过来影响其他网络客户端。

澄清您是在谈论本地管道还是网络管道也很重要。 如果服务器应用程序在运行Microsoft®SQLServer™2000实例的计算机上本地运行,则可以选择本地命名管道协议。 本地命名管道以内核模式运行,速度非常快。

对于TCP / IP套接字,数据传输更加简化并且开销更少。 数据传输还可以利用TCP / IP套接字性能增强机制,例如窗口化,延迟确认等,这在慢速网络中非常有用。 根据应用程序的类型,这种性能差异可能很大。

TCP / IP套接字还支持积压队列,与命名管道相比,它可以提供有限的平滑效果,当您尝试连接到SQL Server时,可能会导致管道繁忙错误。

>通常,套接字在慢速LAN,WAN或拨号网络中是首选,而当网络速度不是问题时,命名管道可能是更好的选择,因为它提供了更多function,易用性和配置选项。

有关TCP / IP的详细信息,请参阅MicrosoftWindowsNT®文档。

如果您需要模拟命名管道客户端的安全凭证 ,那么实际上只有一个选项:)并且命名管道也有更好的名称(尽管DNS SRV记录也可以为TCP端口提供)。

否则,没有太大的区别。 两者都将数据视为字节流,让您自己负责查找消息边界。 命名管道还有一个为您保留消息边界的附加选项,但是要注意,您必须在消息模式下创建管道并同时显式设置读取模式。

如果我正确理解您的要求,您需要在同一台计算机上运行的进程之间进行通信。 这些进程可能在以交互方式登录的用户的相同安全上下文中运行。

在这种情况下,我应该提到解决方案的不同方面。 一个问题是在应用程序之间共享数据。 另一个问题是协议,它定义了如何访问和修改公共数据以及如何进行流程之间的通信 。 例如,您可以拥有一个提供数据的流程,而另一个流程可以订阅数据。 另一种情况:您可以拥有所有应用程序都可以读取或修改的公共数据,您只需要确保没有人同时修改共享数据,或者在另一次修改期间没有人访问数据。 原因可能是许多其他不同的通信场景。

根据这方面,我建议你在问题中不包括其他两个选项:

  • 用法内存映射文件 (见这里和这里 )
  • COM接口的用法

这两种方式都可以在.NET和非托管C ++中很好地实现。 从性能的角度来看,使用内存映射文件是最好的方法。 如果您创建的View将与某个物理文件无关,那么您将只拥有可在进程之间使用的公共内存。 您可以另外使用互斥锁或事件来控制多个应用程序不会同时使用内存。

在最简单的场景中,您甚至可以在C ++中使用#pragma data_seg将一些数据放在DLL的命名部分中,并使用/ SECTION选项(如/SECTION:.MYSEC,RWS )来共享数据。 您可以在所有.NET应用程序和所有非托管C ++应用程序中使用DLL来访问公共数据。 通过这种方式,您可以通过简单的方式访问公共数据。

如果您需要一些更复杂的通信场景,那么使用C ++ / .NET中的COM接口的方法可能是最佳选择。 如果我建议您逐步描述如何使用COM接口在.NET中实现Primary Interop Assembly并在.NET和C ++ COM中使用它进行通信的文章。