0

背景:我最近开始java.nio在我的项目中使用 Android 的VpnService. 在我的实现中,我将由 the方法FileDescriptor返回的内容包装到 a中,如下所示。establish()VpnServicejava.nio.FileChannel

private val outboundNetworkChannel = FileInputStream(fd).channel

之后,我有一个 kotlin 协程,它FileChannel无限期地读取并处理出站 IPv4 / IPv6 数据包。

问题:下面提到的代码片段有效,但我看到很多空读取发生在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
    }

我在寻找什么:事实上,我知道这FileChannel是一个阻塞通道,在这种情况下,由于通道由网络接口​​支持,它可能没有准备好读取的数据包。有/没有更好的方法可以FileChannel在不浪费宝贵的 CPU 周期的情况下实现更有效的实现吗?我也对新想法持开放态度:)

4

1 回答 1

0

在浏览了 Android Docs for 后,我设法弄清楚了这一点VpnService。默认情况下,当使用非阻塞模式建立 VPN 连接VpnService.Builderfd。从 API 级别 21 开始,一个可以setBlocking(true).

如文档中所述public VpnService.Builder setBlocking (boolean blocking)

将 VPN 接口的文件描述符设置为阻塞/非阻塞模式。默认情况下,建立()返回的文件描述符是非阻塞的。

于 2020-05-22T13:13:59.133 回答