C#套接字与管道

时间:2012-06-04 20:42:52

标签: c# winapi sockets network-programming named-pipes

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

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

  • Tcp套接字
  • 命名管道

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

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

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

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

3 个答案:

答案 0 :(得分:5)

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

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

来自msdn的其他一些信息:

  

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

     

对于命名管道,网络通信通常更多   互动。在另一个对等方要求之前,对等方不会发送数据   使用读命令。网络阅读通常涉及一系列   peek在开始读取数据之前命名管道消息。这些可以   在网络速度慢的情况下会非常昂贵并导致过多的网络流量,   这反过来会影响其他网络客户端。

     

澄清您是否在谈论本地管道也很重要   或网络管道。如果服务器应用程序在本地运行   运行Microsoft®SQLServer™2000实例的计算机,本地   命名管道协议是一种选择。本地命名管道在内核中运行   模式并且非常快。

     

对于TCP / IP套接字,数据传输更加简化并具有   减少开销。数据传输还可以利用TCP / IP   套接字性能增强机制,如窗口,延迟   承认,等等,这可能是一个非常有益的缓慢   网络。取决于应用程序的类型,这样的性能   差异可能很大。

     

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

     

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

     

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

答案 1 :(得分:2)

如果您需要impersonate the named pipe client's security credentials,那么实际上只有一个选项:)并且命名管道也有更好的名称(尽管DNS SRV记录也可以提供TCP端口的那些)。

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

答案 2 :(得分:1)

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

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

根据这方面,我会建议您将其他两个选项包括在您的问题中:

  • 使用内存映射文件(请参阅herehere
  • 使用COM接口

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

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

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