Golang TCPConn Gob 通信

huangapple go评论75阅读模式
英文:

Golang TCPConn Gob Communication

问题

我遇到了gob协议的问题(或者可能是网络方面的问题,我对此了解较少),我不明白为什么下面的代码不能正常工作。它只是一个简单的示例,用于维持一个打开的TCP连接,并通过该连接发送多个gob。代码可以发送和接收,但经常会损坏数据。

谢谢您的帮助。

package main

import (
	"encoding/gob"
	"fmt"
	"net"
	"strconv"
	"time"
)

type Message struct {
	Msg string
}

func main() {
	gob.Register(new(Message))

	clientAddr, err := net.ResolveTCPAddr("tcp", "localhost:12346")
	if err != nil {
		fmt.Println(err)
	}
	serverAddr, err := net.ResolveTCPAddr("tcp", "localhost:12345")
	if err != nil {
		fmt.Println(err)
	}

	serverListener, err := net.ListenTCP("tcp", serverAddr)
	if err != nil {
		fmt.Println(err)
	}
	conn, err := net.DialTCP("tcp", clientAddr, serverAddr)
	if err != nil {
		fmt.Println(err)
	}
	serverConn, err := serverListener.AcceptTCP()
	if err != nil {
		fmt.Println(err)
	}
	done := false
	go func() {
		for !done {
			recieveMessage(serverConn)
		}
	}()
	for i := 1; i < 1000; i++ {
		sent := Message{strconv.Itoa(i)}
		sendMessage(sent, conn)
	}
	time.Sleep(time.Second)
	done = true
}

func sendMessage(msg Message, conn *net.TCPConn) {
	enc := gob.NewEncoder(conn)
	err := enc.Encode(msg)
	if err != nil {
		fmt.Println(err)
	}
}

func recieveMessage(conn *net.TCPConn) {
	msg := new(Message)
	dec := gob.NewDecoder(conn) // Will read from network.
	err := dec.Decode(msg)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("Client recieved:", msg.Msg)
}
英文:

I'm having issues with the gob protocol (or maybe networking in general, where my knowledge is weak), and I don't understand why the following code does not work properly. It is just supposed to be a simple example of maintaining an open TCP connection, and sending multiple gobs through it. The code will send, and receive, but often corrupts its data.
Thank you in advance.

package main
import (
&quot;encoding/gob&quot;
&quot;fmt&quot;
&quot;net&quot;
&quot;strconv&quot;
&quot;time&quot;
)
type Message struct {
Msg string
}
func main() {
gob.Register(new(Message))
clientAddr, err := net.ResolveTCPAddr(&quot;tcp&quot;, &quot;localhost:12346&quot;)
if err != nil {
fmt.Println(err)
}
serverAddr, err := net.ResolveTCPAddr(&quot;tcp&quot;, &quot;localhost:12345&quot;)
if err != nil {
fmt.Println(err)
}
serverListener, err := net.ListenTCP(&quot;tcp&quot;, serverAddr)
if err != nil {
fmt.Println(err)
}
conn, err := net.DialTCP(&quot;tcp&quot;, clientAddr, serverAddr)
if err != nil {
fmt.Println(err)
}
serverConn, err := serverListener.AcceptTCP()
if err != nil {
fmt.Println(err)
}
done := false
go func() {
for !done {
recieveMessage(serverConn)
}
}()
for i := 1; i &lt; 1000; i++ {
sent := Message{strconv.Itoa(i)}
sendMessage(sent, conn)
}
time.Sleep(time.Second)
done = true
}
func sendMessage(msg Message, conn *net.TCPConn) {
enc := gob.NewEncoder(conn)
err := enc.Encode(msg)
if err != nil {
fmt.Println(err)
}
}
func recieveMessage(conn *net.TCPConn) {
msg := new(Message)
dec := gob.NewDecoder(conn) // Will read from network.
err := dec.Decode(msg)
if err != nil {
fmt.Println(err)
}
fmt.Println(&quot;Client recieved:&quot;, msg.Msg)
}

答案1

得分: 3

问题在于解码器可以从下一条消息中缓冲数据。当这种情况发生时,下一个新的解码器会从消息的中间开始。修复方法是使用单个编码器和解码器。

func main() {
    ...
    dec := gob.NewDecoder(conn) // 从网络读取数据。
    enc := gob.NewEncoder(serverConn)
    go func() {
        for !done {
            recieveMessage(dec)
        }
    }()

    for i := 1; i < 1000; i++ {
        sent := Message{strconv.Itoa(i)}
        sendMessage(sent, enc)
    }
    ...
}

func sendMessage(msg Message, enc *gob.Encoder) {
    err := enc.Encode(msg)
    if err != nil {
        fmt.Println(err)
    }
}

func recieveMessage(dec *gob.Decoder) {
    msg := new(Message)
    err := dec.Decode(msg)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println("客户端接收到:", msg.Msg)
}

在 playground 中运行

英文:

The problem is that the decoder can buffer data from the next message. When this happens, the next new decoder starts in the middle of a message. The fix is to use a single encoder and decoder.

func main() {
...
dec := gob.NewDecoder(conn) // Will read from network.
enc := gob.NewEncoder(serverConn)
go func() {
for !done {
recieveMessage(dec)
}
}()
for i := 1; i &lt; 1000; i++ {
sent := Message{strconv.Itoa(i)}
sendMessage(sent, enc)
}
...
}
func sendMessage(msg Message, enc *gob.Encoder) {
err := enc.Encode(msg)
if err != nil {
fmt.Println(err)
}
}
func recieveMessage(dec *gob.Decoder) {
msg := new(Message)
err := dec.Decode(msg)
if err != nil {
fmt.Println(err)
}
fmt.Println(&quot;Client recieved:&quot;, msg.Msg)
}

Run it in the playground

huangapple
  • 本文由 发表于 2017年6月23日 00:40:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/44705094.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定