连续 Encode/Decode 使用 GOB
Consecutive Encode/Decode using GOB
我是 Golang 套接字编程的新手。当我尝试从客户端向服务器发送一条消息时,它运行良好。但是,当我尝试连续发送 10 条消息时,出现错误。要搜索的任何 clues/keywords。请查找随附的示例代码。
Server.go
package main
import (
"encoding/gob"
"fmt"
"net"
"os"
)
func main() {
tcpAddr, err := net.ResolveTCPAddr("tcp4", ":5555")
checkError("ResolveTCPAddr", err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError("ListenTCP", err)
conn, err := listener.Accept()
checkError("Accept", err)
for i := 0; i < 10; i++ {
var s string
dec := gob.NewDecoder(conn)
err = dec.Decode(&s)
checkError("Decode", err)
fmt.Println(s)
}
}
func checkError(info string, err error) {
if err != nil {
fmt.Fprintf(os.Stderr, info+": Run - Fatal error: %s\n", err.Error())
os.Exit(1)
}
}
Client.go
package main
import (
"encoding/gob"
"fmt"
"net"
"os"
)
func main() {
tcpAddr, err := net.ResolveTCPAddr("tcp4", ":5555")
checkError("ResolveTCPAddr", err)
conn, err := net.DialTCP("tcp", nil, tcpAddr)
checkError("DialTCP", err)
for i := 0; i < 10; i++ {
enc := gob.NewEncoder(conn)
err = enc.Encode("test")
checkError("Encode", err)
}
}
func checkError(info string, err error) {
if err != nil {
fmt.Fprintf(os.Stderr, info+": Run - Fatal error: %s\n", err.Error())
os.Exit(1)
}
}
屏幕:
test
test
test
test
test
Decode: Run - Fatal error: EOF
exit status 1
问题在于解码器会缓冲来自底层 reader 的数据,并且缓冲的数据可能包含来自流中稍后消息的数据。当应用程序丢弃解码器时,缓冲数据将被丢弃。后来的解码器 returns 出错,因为它正在读取不完整的消息。
这个问题有一个简单的解决方法。 gob 包旨在读取和写入值流。在循环外创建编码器和解码器,让包处理消息框架。
enc := gob.NewEncoder(conn)
for i := 0; i < 10; i++ {
err = enc.Encode("test")
checkError("Encode", err)
}
dec := gob.NewDecoder(conn)
for i := 0; i < 10; i++ {
var s string
err = dec.Decode(&s)
checkError("Decode", err)
fmt.Println(s)
}
如果出于某种原因必须在循环内创建编码器和解码器,则应用程序必须实施消息框架以防止解码器读取多个值。构建消息的一种方法是让客户端在 gob 编码值之前写入一个长度前缀。服务器读取长度,然后限制解码器读取该字节数。
我是 Golang 套接字编程的新手。当我尝试从客户端向服务器发送一条消息时,它运行良好。但是,当我尝试连续发送 10 条消息时,出现错误。要搜索的任何 clues/keywords。请查找随附的示例代码。
Server.go
package main
import (
"encoding/gob"
"fmt"
"net"
"os"
)
func main() {
tcpAddr, err := net.ResolveTCPAddr("tcp4", ":5555")
checkError("ResolveTCPAddr", err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError("ListenTCP", err)
conn, err := listener.Accept()
checkError("Accept", err)
for i := 0; i < 10; i++ {
var s string
dec := gob.NewDecoder(conn)
err = dec.Decode(&s)
checkError("Decode", err)
fmt.Println(s)
}
}
func checkError(info string, err error) {
if err != nil {
fmt.Fprintf(os.Stderr, info+": Run - Fatal error: %s\n", err.Error())
os.Exit(1)
}
}
Client.go
package main
import (
"encoding/gob"
"fmt"
"net"
"os"
)
func main() {
tcpAddr, err := net.ResolveTCPAddr("tcp4", ":5555")
checkError("ResolveTCPAddr", err)
conn, err := net.DialTCP("tcp", nil, tcpAddr)
checkError("DialTCP", err)
for i := 0; i < 10; i++ {
enc := gob.NewEncoder(conn)
err = enc.Encode("test")
checkError("Encode", err)
}
}
func checkError(info string, err error) {
if err != nil {
fmt.Fprintf(os.Stderr, info+": Run - Fatal error: %s\n", err.Error())
os.Exit(1)
}
}
屏幕:
test
test
test
test
test
Decode: Run - Fatal error: EOF
exit status 1
问题在于解码器会缓冲来自底层 reader 的数据,并且缓冲的数据可能包含来自流中稍后消息的数据。当应用程序丢弃解码器时,缓冲数据将被丢弃。后来的解码器 returns 出错,因为它正在读取不完整的消息。
这个问题有一个简单的解决方法。 gob 包旨在读取和写入值流。在循环外创建编码器和解码器,让包处理消息框架。
enc := gob.NewEncoder(conn)
for i := 0; i < 10; i++ {
err = enc.Encode("test")
checkError("Encode", err)
}
dec := gob.NewDecoder(conn)
for i := 0; i < 10; i++ {
var s string
err = dec.Decode(&s)
checkError("Decode", err)
fmt.Println(s)
}
如果出于某种原因必须在循环内创建编码器和解码器,则应用程序必须实施消息框架以防止解码器读取多个值。构建消息的一种方法是让客户端在 gob 编码值之前写入一个长度前缀。服务器读取长度,然后限制解码器读取该字节数。