Problem
I have a use case where I need to Peek
at exactly the first TCP packet, whatever length it may be.
Snippet
I would have expected this to work:
conn, err := sock.Accept()
if nil != err {
panic(err)
}
// plenty of time for the first packet to arrive
time.Sleep(2500 * 1000000)
bufConn := bufio.NewReader(conn)
n := bufConn.Buffered()
fmt.Fprintf(os.Stdout, "Size of Buffered Data %d
", n)
However, even though I am positive that the data has arrived it still shows that 0 bytes are buffered.
Full Test Application
Here's a full test program:
package main
import (
"bufio"
"fmt"
"net"
"os"
"strconv"
"time"
)
func main () {
addr := ":" + strconv.Itoa(4080)
sock, err := net.Listen("tcp", addr)
if nil != err {
panic(err)
}
conn, err := sock.Accept()
if nil != err {
panic(err)
}
bufConn := bufio.NewReader(conn)
var n int
for {
n = bufConn.Buffered()
fmt.Fprintf(os.Stdout, "Size of Buffered Data %d
", n)
if 0 != n {
break
}
time.Sleep(2500 * 1000000)
}
first, err := bufConn.Peek(n)
if nil != err {
panic(err)
}
fmt.Fprintf(os.Stdout, "[Message] %s
", first)
}
Testing
And how I've been testing:
telnet localhost 4080
Hello, World!
This works equally well:
echo "Hello, World!" | nc localhost -p 4080
However, if I call Peek(14)
directly the data is obviously there.
Why?
I'm dealing with an application-specific use case - magic byte detection when multiplexing multiple protocols over a single port.
In theory packet sizes are unreliable, but in practice a small hello packet of a few bytes will not be made smaller by any routers in the path and the application will not send more data until it receives the handshake response.
The Kicker
I'm supporting exactly one protocol that requires the server to send its hello packet first, which means that if after a wait of 250ms no packet has been received, the server will assume that this special protocol is being used and send its hello.
Hence, it will be best if I can know if data exists in the underlying buffer without doing any Read()
or Peek()
beforehand.