【发布时间】:2022-01-23 15:08:28
【问题描述】:
我正在尝试从 HTTP 请求中读取数据
如果我的缓冲区大小是 1024 字节并且传入的消息是 768 字节,那么它可以完美运行,我可以看到缓冲区未满,在这种情况下我可以假设它已完成
read=692, buffer=java.nio.HeapByteBuffer[pos=692 lim=1024 cap=1024] :: read < cap
如果我的缓冲区大小是 512,我仍然可以确定请求何时完成
read=512, buffer=java.nio.HeapByteBuffer[pos=512 lim=512 cap=512]
read=160, buffer=java.nio.HeapByteBuffer[pos=160 lim=512 cap=512] :: read < cap
在缓冲区大小为 64 时,它仍然有效
read=64, buffer=java.nio.HeapByteBuffer[pos=64 lim=64 cap=64]
...
read=64, buffer=java.nio.HeapByteBuffer[pos=64 lim=64 cap=64]
read=32, buffer=java.nio.HeapByteBuffer[pos=32 lim=64 cap=64] :: read < cap
当我进入个位数时,通道似乎正在读取垃圾数据并填满缓冲区
read=7, buffer=java.nio.HeapByteBuffer[pos=7 lim=7 cap=7]
...
read=7, buffer=java.nio.HeapByteBuffer[pos=7 lim=7 cap=7]
read=7, buffer=java.nio.HeapByteBuffer[pos=7 lim=7 cap=7] :: read == cap ?
这意味着我永远不知道何时读取了所有数据 缓冲区大小为 7,我希望最后一个是
692 % 7 = 98
692 - (98*7) = 6
我期待看到
read=6, buffer=java.nio.HeapByteBuffer[pos=6 lim=7 cap=7]
但我看到的是 read=7
如果我将缓冲区的大小与 http 请求的大小完全一致,我会看到
read=692, buffer=java.nio.HeapByteBuffer[pos=692 lim=692 cap=692] :: read == cap ?
但它永远不会回到 channel.read::completed 直到我刷新浏览器,然后 read 转到 -1,但是下一个请求挂起并且永远不会达到 read = -1 以触发通道关闭。
read=692, buffer=java.nio.HeapByteBuffer[pos=692 lim=692 cap=692]
read=-1, buffer=java.nio.HeapByteBuffer[pos=0 lim=692 cap=692]
DONE, closing channel
read=692, buffer=java.nio.HeapByteBuffer[pos=692 lim=692 cap=692] << hangs here until refresh, but then the next request does the same again
关于如何使“末端检测”更可靠的任何想法?
AsynchronousServerSocketChannel.open().let { server ->
server.bind(InetSocketAddress(8080))
// accept next socket
server.accept(ByteBuffer.allocate(bufferSize), object : CompletionHandler<AsynchronousSocketChannel, ByteBuffer> {
override fun completed(channel: AsynchronousSocketChannel, buffer: ByteBuffer) {
// accept next
server.accept(ByteBuffer.allocate(bufferSize), this)
channel.read(
buffer,
channel,
object : CompletionHandler<Int, AsynchronousSocketChannel> {
override fun completed(read: Int, channel: AsynchronousSocketChannel) {
println(("read=$read, buffer=$buffer"))
if (read > 0 || buffer.position() > 0) {
buffer.rewind()
channel.read(
buffer,
channel,
this
)
} else {
println("DONE, closing channel")
channel.close()
}
}
override fun failed(exception: Throwable, channel: AsynchronousSocketChannel) {
exception.printStackTrace()
channel.close()
}
}
)
}
override fun failed(exception: Throwable, attachment: ByteBuffer?) {
exception.printStackTrace()
}
})
}
【问题讨论】:
-
docs 的重要部分是 "-1 如果没有字节可以读取因为通道已到达流尾。" i> 只有当通道在另一侧关闭时,您才能到达流尾。
-
这是有道理的,与我所看到的相符。我需要将此数据流视为没有尽头。
标签: java kotlin sockets asynchronous serversocket