进行涉及 Java 的 RAW 套接字编程的最佳方法

Posted

技术标签:

【中文标题】进行涉及 Java 的 RAW 套接字编程的最佳方法【英文标题】:Best way to do RAW socket programming involving Java 【发布时间】:2011-04-20 18:38:29 【问题描述】:

我有一些现有的 C 代码使用 ICMP 原始套接字执行 Ping,我需要在 Java 中使用此代码,因为 Java 不支持 ICMP 包。当我将代码包装在JNI中并调用它时,C代码在执行时无法获取套接字:

socket(AF_INET, SOCK_RAW, 1);

我猜 Java 已经放弃了一些特权,这些特权会禁止在 Java 进程中使用原始套接字。这个我必须找到解决办法。

我观察到以下情况:

如果我编写一个 C 程序并使用运行时从 Java 调用它,则分叉的代码可能会打开套接字。 如果我从 Eclipse 运行此本机代码,它也运行良好。我猜这是因为 Eclipse 是从 eclipse.exe 启动的,而不是从 java.exe 启动的。

这意味着我可以通过选择这两种策略之一来解决我的问题,但我都不喜欢。有没有其他方法可以让 Java 接受 JNI 代码正在打开这个套接字?

编辑: 我对这个问题的研究越多,我认为它一定是与 Java 启动方式有关的 Windows 7 相关问题。

如果您让 Windows 运行,或者如果您在 Windows 以外的其他平台上,也可以使用 InetAddress.isReachable() 方法。

【问题讨论】:

【参考方案1】:

也许使用现有的 Java 本机套接字库?这样您就不必担心编写 JNI 库了。

见:http://www.savarese.com/software/rocksaw/

【讨论】:

这个库看起来很棒。虽然我们的原生代码已经在做同样的事情,所以我的问题一定是与 windows 相关的。 是的,我发现编写 JNI 库有点痛苦。所以,当有疑问时——使用已经存在的东西。你是让这个库在 Windows 7 上工作还是失败了? 我们决定使用 Runtime.exec(),因为我们必须解决它并继续前进。我认为您的答案是迄今为止最好的答案,它应该确实解决了我的问题,尽管不是我的问题,所以我会接受它:) 这也是唯一的答案 =P。但除了使用某种形式的 JNI 库之外,我真的想不出任何其他好的解决方案。或者做一些奇怪的过于复杂的 IPC。 @Andy: savarese.com 似乎不再存在或不再响应。还有其他资源吗?【参考方案2】:

你不妨试试java.net.InetAddress.isReachable()方法,从 J2SE5 开始就可以使用了。

但它在 Windows 中无法正常工作。见:http://bordet.blogspot.com/2006/07/icmp-and-inetaddressisreachable.html

【讨论】:

这种方法不适合我们需要做的用例,我们确实需要它在Windows上也能工作。 此方法仅在您拥有 root 帐户权限时才能正常工作 - 在这种情况下它会发送原始 ICMP ECHO 请求,否则它会尝试在端口 7(回显服务)上建立 TCP 连接,该端口并不总是打开.因此,在某些情况下,当 Java 尚未从 root 帐户运行时,它会失败。

以上是关于进行涉及 Java 的 RAW 套接字编程的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

python raw socket 介绍

12.5-全栈Java笔记:Java网络编程

SOCK_RAW编程

Python Socket Client及Server简单编程

Java 中的套接字最佳实践

Linux网络编程和套接字