[英]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.在我的实现中,我将
VpnService
的establish()
方法返回的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.