【问题标题】:Java NIO FileChannel - Empty reads from Android TUN network interfaceJava NIO FileChannel - 从 Android TUN 网络接口读取空
【发布时间】:2020-09-02 03:40:02
【问题描述】:

上下文:我最近开始在我的项目中使用java.nio,该项目利用了Android 的VpnService。在我的实现中,我将VpnServiceestablish() 方法返回的FileDescriptor 包装成java.nio.FileChannel,如下所示。

private val outboundNetworkChannel = FileInputStream(fd).channel

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

问题:下面提到的 sn-p 有效,但我看到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周期?我也乐于接受新想法:)

【问题讨论】:

  • fd 是如何进入非阻塞模式的?
  • @user207421 好像是在非阻塞模式下默认从Android VpnService检索到的fd。

标签: java android kotlin nio android-vpn-service


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    • 2013-03-14
    • 2010-12-08
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多