1

我似乎无法在任何地方找到答案,我试图在 Java 中获取一个套接字,并交出它的文件描述符编号,以便我可以在 C 二进制文件中使用它(fd 将作为参数)。

我已经使用反射获得了 FileDescriptor ......但无法在任何地方访问实际数字。

我知道其他人建议使用 JNI,但如果可能的话,我想将它保留在 Java 中(并且无法完全弄清楚如何去做)

4

2 回答 2

3

在 Java 7 中,您可以将 a 强制SocketInputStream转换为 a FileInputStream,然后调用getFD()以获取FileDescriptor对象。

然后您可以使用反射来访问 FileDescriptor 对象的private int fd字段。(您使用该Class.getDeclaredField(...)方法获取字段,调用Field.setAccessible(true),然后使用 获取该字段的值Field.getInt(...)。)


请注意,这样做可能会使您的代码平台依赖。无法保证特定私有字段将出现在较旧的......或即将推出的 Java 版本中,或其他供应商/供应商完成的 Java 实现中。

于 2012-07-12T16:07:54.017 回答
0

Stephen C 的回答解决了如何获取 a FileDescriptor,但这是从该对象获取文件描述符编号的方法。在 Windows 上,FileDescriptor使用long handle而不是在int fd内部使用,因此此方法首先检查是否handle已使用,如果使用则返回,否则返回返回fd。我没有在 OP 使用的套接字上对此进行测试,但我想WindowsJVM 仍然使用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;
}
于 2018-01-03T02:16:05.613 回答