Reputation: 662
I am trying to read from a tcp connection in Go. I have a specific header format I am trying to parse first. So read the first 12 bytes which has the info associated with the header. And that tells me that the remaining message length is a certain amount of bytes. In this case 1607 bytes. I tried the following code where I read the header bytes, and then tried to read the remaining bytes.
import ("net"
log "github.com/sirupsen/logrus"
"bytes"
"encoding/binary"
)
func handleRequest(conn net.Conn) {
// Structs to make header parsing easiers
type encapSTHdrMsgType uint16
type encapSTHdrMsgEncap uint16
type encapSTHdr struct {
MsgType encapSTHdrMsgType
MsgEncap encapSTHdrMsgEncap
MsgHdrVersion uint16
Msgflag uint16
Msglen uint32
}
// Make a buffer to hold header data.
headerBuf := make([]byte, 12)
// Read the incoming header info into the buffer.
_, err := conn.Read(headerBuf)
if err != nil {
log.Debug("Error reading:", err.Error())
}
// Header is in big endian
var header encapSTHdr
headerReader := bytes.NewReader(headerBuf)
err = binary.Read(headerReader, binary.BigEndian, &header)
if err != nil {
log.Debugf("Could not read header bytes into the buffer: %v", err)
}
messageBuf := make([]byte, header.Msglen)
messageBufLen, err := conn.Read(messageBuf)
if err != nil {
log.Debugf("Error reading messages: %s", err.Error())
}
log.Debugf("The message buffer length is: %d", messageBufLen)
log.Debugf("The header message length is: %d", header.Msglen)
}
When I try reading the remaining bytes by making a new buffer of the desired length of 1607, I get a new byte array with data but it is only of length 1228. Hence, I have two questions:
1) Why does conn.Read()not read the remaining bytes?
2) Now I am aware I can use a for loop until I have read the desired amount of bytes and break when done but I was wondering if there was a better way to do this?
Upvotes: 4
Views: 881
Reputation: 120941
Read returns when data is available, not when it fills the buffer. Use io.ReadFull() to read until the buffer is full or there's an error reading from the connection.
_, err := io.ReadFull(conn, headerBuf)
...
_, err := io.ReadFull(conn, messageBuf)
Upvotes: 7