Java NIO FileChannel - 从 Android TUN 网络接口清空读取
Java NIO FileChannel - Empty reads from Android TUN network interface
上下文: 我最近开始在我的项目中使用 java.nio
,它利用了 Android 的 VpnService
。在我的实现中,我将 VpnService
的 establish()
方法返回的 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 周期?我也乐于接受新想法:)
我在研究了 VpnService
的 Android 文档后设法解决了这个问题。默认情况下,当使用 VpnService.Builder
建立 VPN 连接时,fd
处于非阻塞模式。从 API 21 级开始,可以 setBlocking(true)
。
如 public VpnService.Builder setBlocking (boolean blocking)
的文档中所述
Sets the VPN interface's file descriptor to be in
blocking/non-blocking mode. By default, the file descriptor returned
by establish() is non-blocking.
上下文: 我最近开始在我的项目中使用 java.nio
,它利用了 Android 的 VpnService
。在我的实现中,我将 VpnService
的 establish()
方法返回的 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 周期?我也乐于接受新想法:)
我在研究了 VpnService
的 Android 文档后设法解决了这个问题。默认情况下,当使用 VpnService.Builder
建立 VPN 连接时,fd
处于非阻塞模式。从 API 21 级开始,可以 setBlocking(true)
。
如 public VpnService.Builder setBlocking (boolean blocking)
Sets the VPN interface's file descriptor to be in blocking/non-blocking mode. By default, the file descriptor returned by establish() is non-blocking.