强制 WCF 通道到 IP 地址
Posted
技术标签:
【中文标题】强制 WCF 通道到 IP 地址【英文标题】:force WCF channel to ip address 【发布时间】:2014-12-15 03:23:45 【问题描述】:我有两台计算机,它们通过以太网连接,我已经建立了 WCF 连接,这一切正常,但是当我在本地 pc 上托管与我想要通信的相同的 wcf 然后执行通过通道请求 wcf,请求不会发送到远程 pc,而是发送到我的本地 pc。有没有办法强制来自频道的 wcf 请求通过特定的 ipaddress 而不仅仅是任何一个?
我将尝试解释我如何使用它:
有两台计算机,它们都相似,并且有两个网络适配器,它们具有相同的 ipaddess 并运行相同的 wcf 软件。例如,适配器 1 的 ipaddress 是:10.10.10.1,另一个适配器在同一台电脑上是 10.10.10.2,另一台电脑是相似的。现在这两台电脑需要通信,所以我在交叉示例中连接两个网络适配器:pc 1 网络适配器一个连接到 pc 2 网络适配器 2。这样它们以 2 种方式连接。因此,如果我想与一个简单的套接字从一个到另一个进行通信并通过第二个适配器返回,这一切都很好,因为我可以将一个套接字绑定到一个 IP 地址,并且它将通过它绑定到的适配器发送它。但这似乎不适用于 WCF。如果我在一台电脑上有两台主机,一台用于适配器 10.10.10.1,一台在 10.10.10.2 上用于另一台适配器,并且我向远程 pc 上的 10.10.10.2 发送消息,它将通过第二个网络适配器进入.
PC1 network adapter 1 (10.10.10.1) <--direct patch cable connection--> PC2 network adapter 2 (10.10.10.2)
PC1 network adapter 2 (10.10.10.2) <--direct patch cable connection--> PC2 network adapter 1 (10.10.10.1)
这些连接箭头是直接连接跳线!
所有网络适配器都有一个 wcf 托管,并且两台 pc 上的软件是相同的。
这都是为了冗余而做的,多于两台电脑可以用这个连接成一个链。
这是我如何设置对远程主机的请求的一个小例子:
public void Test()
string endPoint = "net.tcp://10.10.10.2:9985/connection";
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
binding.ListenBacklog = 2000;
binding.MaxConnections = 2000;
binding.TransferMode = TransferMode.Buffered;
binding.MaxReceivedMessageSize = 104857600;
binding.SendTimeout = new TimeSpan(0, 1, 0);
binding.CloseTimeout = new TimeSpan(0, 0, 1);
binding.OpenTimeout = new TimeSpan(0, 0, 1);
binding.ReceiveTimeout = new TimeSpan(0, 1, 0);
//binding.HostNameComparisonMode = HostNameComparisonMode.Exact;
//binding.PortSharingEnabled = false;
ChannelFactory<Connection> pipeFactory = new ChannelFactory<Connection>(binding, new EndpointAddress(endPoint));
var pipeProxy = this.ChannelFactory.CreateChannel();
//fictional method: pipeProxy.SendRequestTunnelTo("10.10.10.1"); //this is the ipaddress that it should go out to however it goes out to "10.10.10.2"
//and this is another network adapter also on the local mashine and here is also a wcf host on
((IClientChannel)pipeProxy).AllowOutputBatching = true;
((IClientChannel)pipeProxy).Open();
pipeProxy.SystemRequest(); //do function
【问题讨论】:
您能澄清一下...您不是说两个 IP 地址在两台计算机的 4 个 NIC 之间共享吗?例如,另一台机器有 .3 和 .4 地址吗? 我更新了我的帖子,两台电脑上的IP地址是一样的。并且地址像示例中一样交叉连接。 从您更新的图表中,除非这两台 PC 位于不同的子网中,并且中间发生了 NAT,否则这不是有效的网络设置。应唯一分配 IP 地址。如果第三台计算机尝试 ping 10.10.10.2 怎么办?你希望哪一个回应?您是否有理由尝试像这样共享 IP?可能有更好的方法来实现您的目标 @Basic 对不起,我忘了提到您看到的连接是直接的,所以它只是两个适配器/PC 之间的两条跳线。所以没有双重IP地址,它只是与PC的直接网络连接(IP 10.10.10.1连接到另一台PC 10.10.10.2适配器,反之) 【参考方案1】:好的,这里的问题是路由。如果 windows 认为它可以将流量直接传递到另一个 IP 地址,它会这样做。
在这种情况下,它无法区分它知道的本地 10.10.10.2 和隐藏在 NAT 后面的另一个网络上的一个。
首选的解决方案是不使用相同的子网(因此使用 10.10.10.2 和 10.11.10.2 或类似的子网),但有时可能需要进行重大更改。
下一个最佳选择是使用 NAT 的 IP 地址并使其端口转发。
假设您有这样的设置(其中具有 2 个 IP 地址的框是具有公共和内部 IP 的 NATing 路由器)...
10.10.10.2 --- [10.10.10.1 | 1.2.3.4] --- Internet --- [5.6.7.8 | 10.10.10.1] -- 10.10.10.2
那么左边的机器应该尝试连接到 5.6.7.8,它应该转发连接到右边的机器(反之亦然,右边的机器连接到 1.2.3.4)。
如果您的 WAN 设置使机器看起来在同一个网络中,那么这与在同一个网络上的问题一样大。网络上的路由器都无法确定您指的是哪个 10.10.10.2,
如果您没有使用完全相同的 IP 地址,您也许可以使用 Windows 机器上的路由表来强制解决问题。这可以让您指定优先路由,以便给定 IP 地址的所有流量都通过指定的 NIC 发出。不幸的是,超出这一点,您将无法控制数据包的路由方式,完全取决于网络硬件。如果您有能力在中间硬件上配置路由,则可以将整个路由修复到目的地,但这通常是一项非常繁重的工作,并且在更新/更换套件时可能会被破坏,因为它是非标准的。
如果您决定研究强制路由,请从 Windows route command开始
编辑: Re:强制通过接口路由...
语法是route add target mask gateway costmetric interfaceid
在命令提示符下运行route print
,并在输出顶部记下要使用的接口 ID
然后添加这样的路线:
route add 10.10.10.2 255.255.255.255 10.10.10.2 1 [interface id from above]
在我的机器上
route add 10.10.10.2 255.255.255.255 10.10.10.2 1 11
请注意,在这种情况下,我们告诉它使用 10.0.0.2 作为网关。我不知道这样做的后果是什么,因为试图通过本地绑定端口访问自身的软件可能会非常困惑。最后一个警告:我手头没有可以测试的物理机器,而且虚拟机也不算数,因为它们的网络略有不同。
我们提供的成本指标为 1。这应该给它一个非常高的优先级,这意味着它应该优先于所有其他通往该 IP 地址的路由。
系统重启时路由会丢失。您可以在route add
之后使用-p
标志来使路由持久化。我建议您在确定它按预期工作之前不要这样做。
第二次编辑:我认为你在这里陷入了困境。虽然可能会诱使系统以这种方式工作,但这绝对不是一种常见的用法,而且我找不到任何说它受支持的东西。
您的根本问题似乎是在分配 IP 地址之前无法协商,因为您没有网络连接。
一些想法……
共享 IP 不会很健壮,因此与其分离。不要在 url 中使用固定 IP,而是以编程方式确定另一个 IP 地址。
您可以有两个版本,一个使用 .1/.2,另一个使用 .3/.4。然后,任何 build1 都可以与任何 build2 对话,但不能与 1-1 或 2-2 对话。这有点尴尬,但您无需付出任何努力。
最好为您构建的每台机器分配唯一的 IP,然后提供一种方法来检测另一台机器的地址。 Service location protocol 可能是这种方法的候选者。一旦知道了需要与之通信的 IP 地址,配置 WCF 就应该很简单了。
如果分配唯一 IP 存在问题,您可能会在所有节点上都有 DHCP 服务器,但只有在该网络(对)上不存在另一个服务器时才打开它们。这样一来,每台机器最终都会获得有效的 IP 地址,而无需事先配置。
【讨论】:
我在阅读您的最新评论之前发布了此内容。我正要参加一个会议,但如果我能想到更好的选择,我会回来更新。不幸的是,在大约 15 年的时间里,我没有在没有路由器的情况下完成网络,所以我需要思考一下。路由表可能仍然是一种选择。当我不在时,是否有理由不使用路由器并为 4 个 NIC 分配不同的 IP 地址?哦,您能否编辑您的 Q 以在一台/两台机器上包含route print
的输出(仅限接口列表/IPv4)
如果我使用两个不同的网络子网,问题确实解决了。然而,这确实会扰乱冗余软件背后的设计理念。直接连接而不是通过路由器的原因是额外的故障点,这条通信线路连接两个(或三个)服务器(实际上只是彼此相邻),因此它们可以快速共享数据,并且几乎没有机会失败,因为两条直接的跳线,以及软件的设计。
@Basic 但是我不认为路由是问题,我怀疑 WCF 请求通道去寻找端点 '10.10.10.2:9985' 并在它自己的网络适配器上看到它,并且没有进一步寻找它可能是连接到另一个网卡的远程电脑的可能性。
@Jeff 你对这个问题是正确的,但 是 一个路由问题。如果您查看route print
的输出,您可能会注意到10.10.10.2
被标记为On-link
,这意味着根本不用去网络,它是一个本地接口拥有的地址。我们应该能够强制一条说通过接口 [x] 的路由。有趣的是,机器无法使用自己的本地 IP 地址与自己通信(loopback/127.0.0.1 除外)。问题是,我不确定这会产生什么影响,所以我需要做一些研究
@Basic 用于此通信的网络适配器专用于此目的,因此没有其他通信可以通过此网络适配器。我如何强制它通过特定的界面?我去试试看好不好用。【参考方案2】:
您的端点地址需要识别您的目标 IP 地址。
【讨论】:
ipaddres 是远程 pc 的 ipaddress,但是本地 pc 也有另一个具有相同 ip 和相同主机运行的网络适配器。所以我需要强制它不在那个网络适配器上而是在另一个上。 同一网络的两台机器使用相同的IP地址是不行的。 它们不在同一个网络上,两个适配器都在独立的网络上,与其他主机通信。 wcf 请求不会发送到远程 pc,而是因为另一个网络适配器也具有相同的目标 ipaddress,所以请求是本地的而不是远程的。以上是关于强制 WCF 通道到 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章