带有JNI的ioctl():破损的文件描述符
问题描述:
我试图在Java中与Linux tun驱动程序接口,因为它在这里解释。带有JNI的ioctl():破损的文件描述符
How to interface with the Linux tun driver
但因为你不能调用的ioctl()用java,我现在用的是Java本地接口。只要我不在相同的文件中读写,它工作的很好。
如果我这样做,我得到这个例外,我会通过翻译“的FileDescriptor处于断开状态”:
java.io.IOException: Le descripteur du fichier est dans un mauvais état
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at WriterThread.main(WriterThread.java:54)
这里是Java代码:
public static void main(String[] arg){
File tunFile = new File("/dev/net/tun");
FileOutputStream outStream;
FileInputStream inStream;
try {
inStream = new FileInputStream(tunFile);
outStream = new FileOutputStream(tunFile);
FileDescriptor fd = inStream.getFD();
//getting the file descriptor
Field f = fd.getClass().getDeclaredField("fd");
f.setAccessible(true);
int descriptor = f.getInt(fd);
//use of Java Native Interface
new TestOuvertureFichier().ioctl(descriptor);
while(true){
System.out.println("reading");
byte[] bytes = new byte[500];
int l = 0;
l = inStream.read(bytes);
//the problem seems to come from here
outStream.write(bytes,0,l);
}
} catch (Exception e) {
e.printStackTrace();
}
}
这里C代码:
JNIEXPORT void JNICALL Java_TestOuvertureFichier_ioctl(JNIEnv *env,jobject obj, jint descriptor){
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN;
strncpy(ifr.ifr_name, "tun0", IFNAMSIZ);
int err;
if ((err = ioctl(descriptor, TUNSETIFF, (void *) &ifr)) == -1) {
perror("ioctl TUNSETIFF");exit(1);
}
return;
}
答
文件描述符创建FileInputStream
和FileOutputStream
对象时不被调用创建但是。这意味着你的代码打开两次/ dev/net/tun文件(创建两个不同的文件描述符)。
inStream = new FileInputStream(tunFile);
outStream = new FileOutputStream(tunFile);
因此,读写控制仅应用于inStream
,而不是outStream
。 尝试创建FileOutputStream
,同时使用与FileInputStream
相同的文件描述符。
outStream = new FileOutputStream(inStream.getFD());
编辑:FileInputStream很可能会打开一个只读的FD。正如Jayte所建议的,最好先创建一个RandomAccessFile
,然后用它来创建这两个数据流。
答
注意bytes
应至少interfac的MTU大小e,例如1500字节。每次调用时,tun fd上的read()
都会读取完整的数据包。
在写入tun设备之前,您应该操纵IP头,尤其是接收到的数据包的源地址和目标地址。
答
G. Fiedler是对的,读取应该至少与接口MTU一样大,写入不应超过MTU。除此之外,我会检查:
- 在尝试读取或写入,界面了(IP地址添加XXXX/XX开发TUN0,IP链路集TUN0高达)
- 您打开tun设备只能使用一次,例如使用RandomAccessFile。在这里,我不确定inStream和outStream是否具有相同的文件描述符。
'新FileOutputStream(...)'一定会尝试创建一个新文件。尝试使用* one *'RandomAccessFile'而不是两个文件流。 – EJP