我正在开发一个简单的Go服务器程序,它接收客户端的请求并对其进行处理。代码简化为:
package main
import (
"fmt"
"net"
"os"
)
const (
pduLen = 32
)
func checkError(err error) {
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func main() {
var buffer [4096]byte
var count int
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%s", os.Args[1], os.Args[2]))
checkError(err)
for count < pduLen {
n, err := conn.Read(buffer[count:])
checkError(err)
count += n
}
......
}
我假设每个请求的长度都是32
个字节(只是一个例子)。因为TCP
是流协议,所以我需要使用循环来检查是否读取了整数PDU:
for count < pduLen {
n, err := conn.Read(buffer[count:])
checkError(err)
count += n
}
是否有任何方法可以确保读取完整的PDU?就个人而言,我认为循环代码有点难看。
答案 0 :(得分:1)
它可能取决于您收到的PDU的确切性质,但this example将查找大小,然后阅读所有内容(使用io.ReadFul()
)。
func read(conn net.Conn, key string) string {
fmt.Fprintf(conn, GenerateCommand(OP_GET, key))
if verify(conn) {
var size uint16
binary.Read(conn, binary.LittleEndian, &size)
b := make([]byte, size)
// _, err := conn.Read(b)
_, err := io.ReadFull(conn, b)
if err == nil {
return string(b)
}
}
return ""
}
func verify(conn net.Conn) bool {
b := make([]byte, 1)
conn.Read(b)
return b[0] == ERR_NO_ERROR
}
用于:
conn, err := net.Dial("tcp", ":12345")
if err != nil {
t.Error(err)
}
write(conn, "foo", "bar")
if !verify(conn) {
t.Error("Bad write!")
}
if r := read(conn, "foo"); r != "bar" {
t.Errorf("Bad read! Got %v", r)
}
答案 1 :(得分:0)
在golang-nuts讨论此问题后:How to read an integral network PDU? 代码应该是:
import "io"
......
pdu := make([]byte, pduLen)
io.ReadFull(conn, pdu)