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



上下文:我最近开始在我的项目中使用java.nio,该项目利用了Android的VpnService。在我的实现中,我将VpnServiceestablish()方法返回的FileDescriptor包装到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周期的情况下实现更有效的实现?我也对新想法持开放态度:)

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

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

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

最新更新