gpt4 book ai didi

java - 确定 JNA 下的 setsockopt 平台

转载 作者:行者123 更新时间:2023-12-01 11:47:22 25 4
gpt4 key购买 nike

我正在编写 setsockopt 的实现在 JNA 下。 Java本身supports setsockopt ,但它不支持所有特定于平台的套接字选项。例如,它不支持 [TCP_KEEPIDLE][2]在Linux下。显然,其中许多选项的可移植性不太好,而使用 JNA 会导致可移植性较差;我知道这一点。请不要费心告诉我这个想法非常可怕。

然而,我想做的是让我的代码比只在 Linux 下运行的代码更具可重用性。我希望它能够(尽可能)在多个目标平台上工作。如果套接字选项不可用,它可能会抛出异常。

我的挑战是这样的。 JNA 工作正常,但套接字选项的值在不同平台上有所不同。例如,SO_RCVBUF0x1002在 OS-X 和 8 下在Linux下(我意识到 SO_RCVBUF 可以由普通的Java setSockOpt 控制 - 这是一个很容易使用 lsof 进行测试的示例)。 SO_DONTROUTE5在 Linux 下,和 0x0010在 OS-X 下(并且不能通过 Java setSockOpt 控制)。

所以我想要它做的是采取 enum代表套接字选项的值( SO_SNDBUFSO_RCVBUF 或其他),并在平台相关映射中查找该值,所以我得到 0x1002/0x010在 OS-X 和 8 下/5 Linux 下。

这很简单,但是我如何知道 JNA 下的平台是什么,以便我知道要使用哪个 map ? JNA 必须以某种方式了解自己的平台,否则(我认为)它不知道如何调用 native 库。

package sockettest;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.Socket;

import com.sun.jna.LastErrorException;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;

public class JNASockOpt {

private static Field fdField;
static {
Native.register("c");
try {
fdField = FileDescriptor.class.getDeclaredField("fd");
fdField.setAccessible(true);
} catch (Exception ex) {
fdField = null;
}
}

public static int getInputFd(Socket s) {
try {
FileInputStream in = (FileInputStream)s.getInputStream();
FileDescriptor fd = in.getFD();
return fdField.getInt(fd);
} catch (Exception e) { }
return -1;
}

public static int getOutputFd(Socket s) {
try {
FileOutputStream in = (FileOutputStream)s.getOutputStream();
FileDescriptor fd = in.getFD();
return fdField.getInt(fd);
} catch (Exception e) { }
return -1;
}

public static int getFd(Socket s) {
int fd = getInputFd(s);
if (fd != -1)
return fd;
return getOutputFd(s);
}

// The list of SOL_ and SO_ options is platform dependent
public static final int SOL_SOCKET = 0xffff; // that's under OS-X, but it's 1 under Linux
public static final int SO_RCVBUF = 0x1002; // that's under OS-X, but it's 8 under Linux
public static final int SO_DONTROUTE = 0x0010; // that's under OS-X, but it's 5 under Linux

private static native int setsockopt(int fd, int level, int option_name, Pointer option_value, int option_len) throws LastErrorException;

public static void setSockOpt (Socket socket, int level, int option_name, int option_value) throws IOException {
if (socket == null)
throw new IOException("Null socket");
int fd = getFd(socket);
if (fd == -1)
throw new IOException("Bad socket FD");
IntByReference val = new IntByReference(option_value);
try {
setsockopt(fd, level, option_name, val.getPointer(), 4);
} catch (LastErrorException ex) {
throw new IOException("setsockopt: " + strerror(ex.getErrorCode()));
}
}

public static native String strerror(int errnum);

private JNASockOpt() {
}
}

最佳答案

类(class)com.sun.jna.Platform JNA提供的供JNA本身使用,具有查询操作系统家族和CPU架构的功能。

isMac()isLinux() 的静态方法。

关于java - 确定 JNA 下的 setsockopt 平台,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29053320/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com