2012-07-17 45 views
2

我正在研究一种通信协议,该协议应该通过在本地网络上广播/多播对等体地址来支持自我配置。直观的方式是广播地址,但事实证明,很难可靠地找出当前机器的本地IP地址(取决于配置,您可能会得到“127.0.0.1”或另一个无用的地址) 。请问socket.recvfrom总是返回一个有效的地址吗?

另一种方法是不在广播消息中包含主机地址,而是让接收者在它们的套接字上调用recvfrom,它不仅返回接收到的数据,还返回发送者的地址。正如我所看到的那样,这个调用在Unix和Windows(我的一个需求)上都可用,并且可能还有更多的平台。我现在的问题是,有没有这种情况下,这可能会失败,recvfrom返回一个无法访问或无用的地址?

+2

这个问题会更好的堆栈溢出。 – Blrfl 2012-07-17 10:38:17

+1

@Blrfl:你是对的,我的错。你是否愿意投票赞成离题话题,以便我们可以将它移到那里? – 2012-07-17 12:21:49

+0

我有70分可以做到这一点。但我会给你写一个答案。 :-) – Blrfl 2012-07-17 14:54:40

回答

3

如果你限制这种技术只广播UDP,你应该没问题。唯一可能导致混淆的是双重NAT或发夹式NAT。这只不过是本地的广播而已。

+0

多播(仍然UDP)呢?对于我期望的少数同行来说,这不是必要的,但我想支持不支持广播的IPv6网络。 – 2012-07-17 12:20:42

1

任何地址在任何时候都会变得无法访问(因此您的定义无用)。你的软件应该准备好处理这个问题。

通过枚举接口,您可以可靠地确定系统的IP地址(注意复数,稍后会详细介绍)。你如何做到这一点在不同的平台上会有所不同,因为标准(例如,POSIX)中没有指定应该如何完成的任何内容。许多Unixy系统都有一个getifaddrs()调用; Windows做其他事情。无论哪种方式,隔离该代码应该很容易。

您的软件也不应该假设它遇到的IP是“该”地址。在具有多个接口的系统上(如果您计算环回,这些接口中的大多数接口),路由可能会更改,或者某人可能想要在与默认路由不在相同接口上的网段上运行协议。

如果您要广播一条消息,则需要在每个已启用的接口上执行一次,包括环回,除非您将其配置为以其他方式进行配置。广播也应该从发生这些接口中的每一个,因此它具有正确的地址。你不能假定与任何接口在同一网段上的其他主机知道任何其他接口或有路由到他们的地址。

如果您的协议仅用于连接的网段,从非连接的子网中丢弃数据将是一件合理的事情。