2013-01-24 63 views
1

我们使用Fleck作为我们的Websockets。RemoteEndPoint给出错误的IP地址

当我们在本地测试我们的网络程序时,它一切正常。连接客户端的过程是:

  • 建立TCP连接
  • 发送/接收罕见的TCP报文
  • 开始发送/接收UDP流服务器

的问题是活的服务器上客户端可以接收和发送TCP消息,他们可以发送UDP消息,但他们不要收到 UDP消息。

我们已经调查了它,并且发现服务器上TCP连接的RemoteEndPoint属性具有错误的IP地址。它似乎是我们ISP的IP地址。我们使用此IP地址尝试将UDP消息发送回客户端。由于它具有错误的IP,客户端永远不会收到这些UDP消息。

客户端的实际源IP地址必须在某处已知,因为TCP消息使其恢复正常。我已经通过Fleck源代码并打印出底层System.Net.SocketRemoteEndPoint,但它一直给出错误的IP地址。

是否有人知道发生了什么问题以及我们如何才能公开客户端的实际IP地址?

+0

这是设计。服务器和客户端正在与Internet上的路由器进行通信,后面是您的本地网络。 [NAT](http://en.wikipedia.org/wiki/Network_address_translation)负责弥合路由器与通信所指向的适当内部机器之间的差距。 UDP响应是在双工通信信道上发回的,还是服务器启动了到客户端的任何新连接? – mellamokb

+0

@mellamokb服务器在发回它们之前等待UDP数据包从客户端到达。我有点困惑,为什么服务器可以发送TCP很好,但不是UDP,这不幸的是有点超出了我的专业知识。 –

+0

这对于ServerFault而言更具备ontopic特性。这里没有代码问题,只是错误地设置网络。 – leppie

回答

2

最可能的原因是您的客户端没有公共IP地址,而是网络地址转换(一种非常常见的设置)后的私有地址。常用的私有地址格式为10.X.X.X或192.168.X.X.

NAT设备使用其IP地址替换客户端数据包中的私有地址,该IP地址是公共的。对于外部世界来说,流量似乎来自NAT设备。 NAT的主要优点是它允许许多客户端使用单个公共IP地址(IP地址稀疏)。但NAT引入了一个问题:传入的数据包需要路由到正确的客户端,但它没有客户端IP地址。需要使用其他一些策略来识别哪个客户端应该被路由到哪个客户端,并且这种路由并不总是可能的。

例如,最着名的NAT限制是,您不能简单地在NAT后面启动侦听TCP服务器,然后从外部世界连接到它。原因是NAT设备不知道你的服务器在给定的端口上侦听,因此无法知道来自外部世界的TCP SYN数据包需要传递给你的客户端。解决方法是明确配置NAT设备,将定向到给定端口的SYN数据包路由到特定客户端(端口转发)。

当NAT后面的客户端启动TCP连接时,NAT设备会记住连接的状态(客户端地址,客户端端口,远程地址,远程端口)。因此,当响应到达时,设备知道响应应该通过哪个客户端。当连接关闭时,设备丢弃状态信息。这就是为什么你的客户可以通过TCP进行通信。

但UDP更难处理,因为它是无连接和无状态的。当设备看到一个UDP数据包时,它现在可以知道是否期望有回复,何时不是所有的NAT设备都处理UDP数据流。虽然there is a technique,允许做到这一点。

总结:您看到的问题不是C#特定的。设置从服务器到客户端IP地址的数据包的IP地址不会有帮助,因为它很可能是不可路由的专用地址。要解决此问题,您需要使用可以在两个方向上传递UDP流量的NAT设备。但是,如果您正在开发一个通用客户端以用于许多设置,那么您可能需要重新考虑UDP是否是最佳选择。 TCP连接转发是所有NAT设备都支持的基本功能,但某些设备可能不支持UDP。

+0

近乎+1 - 你在UDB上的陈述是错误的。理论上它们是可以的,但是有一些众所周知的方式来打开UDP。例如:让客户端向服务器发送keepalive数据包,然后服务器可以回答。 UDP是一个通用的协议,它是标准的如何与NAT后面的客户端进行通信。 – TomTom

+0

@TomTom这是真的,但我没有写处理UDP是不可能的,我甚至包含了一个描述UDP打孔技术的链接。 –