Java NIO FileChannel-从Android TUN网络接口读取为空

问题描述 投票:0回答:1

Context:我最近开始在利用Android java.nio的项目中使用VpnService。在我的实现中,我将FileDescriptorestablish()方法返回的VpnService包装到java.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周期?我也对新想法持开放态度:)

java android kotlin nio android-vpn-service
1个回答
0
投票

在浏览VpnService的Android文档后,我设法弄清楚了这一点。默认情况下,使用VpnService.Builder建立VPN连接时,fd处于非阻塞模式。从API级别21开始,可以setBlocking(true)

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

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

© www.soinside.com 2019 - 2024. All rights reserved.