我似乎无法在任何地方找到答案,我试图在 Java 中获取一个套接字,并交出它的文件描述符编号,以便我可以在 C 二进制文件中使用它(fd 将作为参数)。
我已经使用反射获得了 FileDescriptor ......但无法在任何地方访问实际数字。
我知道其他人建议使用 JNI,但如果可能的话,我想将它保留在 Java 中(并且无法完全弄清楚如何去做)
我似乎无法在任何地方找到答案,我试图在 Java 中获取一个套接字,并交出它的文件描述符编号,以便我可以在 C 二进制文件中使用它(fd 将作为参数)。
我已经使用反射获得了 FileDescriptor ......但无法在任何地方访问实际数字。
我知道其他人建议使用 JNI,但如果可能的话,我想将它保留在 Java 中(并且无法完全弄清楚如何去做)
在 Java 7 中,您可以将 a 强制SocketInputStream
转换为 a FileInputStream
,然后调用getFD()
以获取FileDescriptor
对象。
然后您可以使用反射来访问 FileDescriptor 对象的private int fd
字段。(您使用该Class.getDeclaredField(...)
方法获取字段,调用Field.setAccessible(true)
,然后使用 获取该字段的值Field.getInt(...)
。)
请注意,这样做可能会使您的代码平台依赖。无法保证特定私有字段将出现在较旧的......或即将推出的 Java 版本中,或其他供应商/供应商完成的 Java 实现中。
Stephen C 的回答解决了如何获取 a FileDescriptor
,但这是从该对象获取文件描述符编号的方法。在 Windows 上,FileDescriptor
使用long handle
而不是在int fd
内部使用,因此此方法首先检查是否handle
已使用,如果使用则返回,否则返回返回fd
。我没有在 OP 使用的套接字上对此进行测试,但我想Windows
JVM 仍然使用handle
.
public static long fileno(FileDescriptor fd) throws IOException {
try {
if (fd.valid()) {
// windows builds use long handle
long fileno = getFileDescriptorField(fd, "handle", false);
if (fileno != -1) {
return fileno;
}
// unix builds use int fd
return getFileDescriptorField(fd, "fd", true);
}
} catch (IllegalAccessException e) {
throw new IOException("unable to access handle/fd fields in FileDescriptor", e);
} catch (NoSuchFieldException e) {
throw new IOException("FileDescriptor in this JVM lacks handle/fd fields", e);
}
return -1;
}
private static long getFileDescriptorField(FileDescriptor fd, String fieldName, boolean isInt) throws NoSuchFieldException, IllegalAccessException {
Field field = FileDescriptor.class.getDeclaredField(fieldName);
field.setAccessible(true);
long value = isInt ? field.getInt(fd) : field.getLong(fd);
field.setAccessible(false);
return value;
}