我试图从Go中的tcp连接读取.我有一个特定的标题格式,我试图先解析.因此,请读取前12个字节,其中包含与标题关联的信息.这告诉我剩余的消息长度是一定的字节数.在这种情况下1607字节.我尝试了下面的代码,我读取了头字节,然后尝试读取剩余的字节.
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)
}
Run Code Online (Sandbox Code Playgroud)
当我尝试通过创建一个所需长度为1607的新缓冲区来读取剩余的字节时,我得到一个带有数据的新字节数组,但它的长度只有1228.因此,我有两个问题:
1)为什么conn.Read()没有读取剩余的字节?
2)现在我知道我可以使用for循环,直到我读取所需的字节数并在完成时中断,但我想知道是否有更好的方法来做到这一点?
数据可用时读取返回,而不是填充缓冲区时返回.使用io.ReadFull()读取,直到缓冲区已满或从连接读取错误.
_, err := io.ReadFull(conn, headerBuf)
...
_, err := io.ReadFull(conn, messageBuf)
Run Code Online (Sandbox Code Playgroud)