简体   繁体   English

Java NIO FileChannel - 从 Android TUN.network 接口读取空数据

[英]Java NIO FileChannel - Empty reads from Android TUN network interface

Context: I've recently started using java.nio for my project which leverages Android's VpnService .上下文:我最近开始在我的项目中使用java.nio ,它利用了 Android 的VpnService In my implementation, I've wrapped the FileDescriptor that is returned by the establish() method of the VpnService into a java.nio.FileChannel as shown below.在我的实现中,我将VpnServiceestablish()方法返回的FileDescriptor包装到java.nio.FileChannel中,如下所示。

private val outboundNetworkChannel = FileInputStream(fd).channel

After that, I've a kotlin coroutine which reads from the FileChannel indefinitely and processes the outbound IPv4 / IPv6 packets.之后,我有一个 kotlin 协程,它无限期地从FileChannel读取并处理出站 IPv4 / IPv6 数据包。

Issue: The below mentioned snippet works, but I see a lot of empty reads happening from the FileChannel which in turn spins the while loop unnecessarily.问题:下面提到的代码片段有效,但我看到FileChannel发生了很多空读取,这反过来不必要地旋转了while循环。

fun reader() = scope.launch(handler) {
    while (isActive) {
        val pkt = read()
        if(pkt !== DUMMY){
            // Send the read IPv4/IPv6 packet for processing
        }
    }
}

private suspend fun read(): IPDatagram =
    withContext(Dispatchers.IO) {
        val bytes = ByteBufferPool.acquire()
        outboundChannel.read(bytes) // Returns a lot of empty reads with return value as 0
        return@withContext marshal(bytes) // Read IPv4/IPv6 headers and wrap the packet
    }

What I'm looking for: For a fact, I know that FileChannel is a blocking channel and in this case since the channel is backed by a.network interface, it might not have packets ready to be read.我在寻找什么:事实上,我知道FileChannel是一个阻塞通道,在这种情况下,由于通道由网络接口支持,它可能没有准备好读取的数据包。 Is there a better approach with / without FileChannel which would lead to a more efficient implementation without wasting precious CPU cycles?有/没有FileChannel是否有更好的方法可以在不浪费宝贵的 CPU 周期的情况下实现更高效的实现? I'm open to new ideas as well:)我也乐于接受新想法:)

I managed to figure this out after digging through the Android Docs for VpnService .在深入了解VpnService的 Android 文档后,我设法解决了这个问题。 By default, when a VPN connection is established using VpnService.Builder the fd is in non-blocking mode.默认情况下,当使用VpnService.Builder建立 VPN 连接时, fd处于非阻塞模式。 Starting API level 21, one can setBlocking(true) .从 API 级别 21 开始,可以setBlocking(true)

As stated in the docs for public VpnService.Builder setBlocking (boolean blocking)public VpnService.Builder setBlocking (boolean blocking)的文档中所述

Sets the VPN interface's file descriptor to be in blocking/non-blocking mode.将 VPN 接口的文件描述符设置为阻塞/非阻塞模式。 By default, the file descriptor returned by establish() is non-blocking.默认情况下,establish() 返回的文件描述符是非阻塞的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM