如何找到默认网关的地址以及面向它的本地地址?

时间:2018-06-30 09:58:57

标签: c linux routing network-programming ip-address

我正在实现在Linux中工作的端口控制协议(PCP)客户端,该客户端以C语言实现。它需要连接到默认网关才能打开端口。 PCP需要在消息本身中嵌入本地IP地址,而不仅是在IP标头中嵌入(大概是为了检测路径中是否存在不需要的NAT,但这对我来说是一个谜,机器之间可能存在NAT及其默认网关)。 PCP还需要连接到默认网关,并需要其地址。

这引起了两个问题:

  1. 如何查找默认网关的IP地址?
  2. 即使在存在多个接口和IP地址的情况下,如何查找通往默认网关的计算机的IP地址?

1 个答案:

答案 0 :(得分:0)

问题的答案如下:

  1. 可以从@Component(modules = {AndroidInjectionModule.class, MainAppModule.class}) 轻松找到默认网关。这是路线,掩码为零,目的地为零。所有十六进制值均以网络字节顺序排列,因此,如果IP地址需要漂亮地打印或与主机字节顺序进行比较,则可能需要/proc/net/route
  2. 查找通往默认网关的IP地址的最简单方法是创建UDP套接字,而不是ntohl,而是bind()到默认网关,然后使用connect()查找它自动绑定到的IP地址。

有了这些功能,我的PCP客户端绝对不需要任何手动IP地址配置。它会自动检测默认网关和指向默认网关的IP地址。

对于(1),可以使用NETLINK套接字,但是解析getsockname()要容易得多。第二种选择是使用在输出上带有/proc/net/route的{​​{1}}和fork exec,并解析其输出,但这将使程序依赖于外部二进制文件。

(2)的替代方法也可以是使用NETLINK套接字查找本地IP地址,然后尝试推断出哪个地址将用于连接到默认网关,但是让Linux内核执行此操作要容易得多自动扣除并使用netstat读取结果。第二种替代方法可能是在输出上带有pipe的{​​{1}}和getsockname() forkexec,然后解析其输出并确定哪个IP地址是使用(ip的第一个字段提供默认路由的接口,因此接口名称是已知的),但这也将使程序依赖于外部二进制文件,并且ifconfig可能不是始终安装,并且这将需要在用户空间中进行推论。