我正在嘗試從 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()
}
})
}
uj5u.com熱心網友回復:
您通過讀取小于緩沖區大小來檢測流末尾的整個想法是完全錯誤的。
套接字不是基于訊息的,它們是資料流,并且不能保證資料在發送時到達。當您在一側發送 692 位元組時,它可能作為 692 位元組的單次讀取到達,但它可能是例如兩次讀取:400 和 292 位元組。即使讀取緩沖區為 1024 位元組。
檢測流結束的兩種方法是:
- 在發送端關閉socket,在接收端等待
-1。 - 實作某種協議(或使用已經存在的協議)在資料流之上對訊息進行編碼。最簡單的就是先發送訊息的大小,然后讀取,只要我們收到預期的資料量。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/390034.html
上一篇:如果我已經填充了iphdr的所有欄位,那么如何計算tcphdr->doff和iphdr->ihl|tcp資料偏移量和ip頭長度
