我正在尝试编写一个程序,该程序将在系统的所有接口上检测跨多种UNIX和Linux的开放端口。对这个网站和其他网站的研究使我的代码类似于:
try {
SocketServer s = new SocketServer(port, 0, host).close();
} catch ( Exception ex ) {
do something here...
}
类似于:
DatagramSocket d = new DatagramSocket(port, host).close();
代码在RHEL 6上运行良好。但是,在AIX 7,HP-UX 11.31和Solaris 10和11上,未检测到某些打开的端口。例如,代码没有报告SSH(TCP 22)打开,并且每个系统上都运行了一个SSH守护程序(这是我连接到系统的方式)。但是SSH守护进程并不是唯一没有报告的开放端口。
我在一个帖子中发现了一条说法,说使用SocketServer似乎在Java 7及更高版本上运行不正常,并建议将代码转换为客户端套接字连接:
Socket s = new Socket(host, port);
此代码工作得更好,但速度慢得多(由于等待关闭/非活动端口上的连接)。它也不是100%准确。 (我可以理解这是一个程序声明了端口但不接受该端口上的连接的情况。)
我应该注意到我使用netstat输出作为我的比较基础。例如,在Linux上:
# netstat --protocol=inet -aln
与其他人相似:
# netstat -f inet -an
我很想使用Java的原生网络来解决这个问题,因为它应该适用于所有目标平台。但我还没有找到一个在所有平台上100%运行的解决方案。
所以,我的问题。有人曾经遇到过这种情况,并找到了适用于多个平台的方法吗?如果是这样,请指点我的方向吗?
谢谢。
约翰
找到了一些额外的信息(感谢一位发现了很多此事的同事)。
1)我运行的所有系统(RHEL 6系统除外)都有双栈(IPv4和IPv6)。控制它的JVM网络属性是 java.net.preferIPv4Stack 属性。可以在找到here的Oracle文档中找到解释。
2)SO_REUSEADDR和SO_REUSEPORT套接字选项也可能涉及一些交互。它上面有一个很好的StackOverflow线程here。
3)最后,JDK中有一个已经解决的错误。这个bug只提到了Windows 7和2008.我把它包含在这里以供参考,万一有人偶然发现这个帖子。链接是here。
Ĵ