0 协议
package protocol
type MsgHead struct {
Len uint
}
type MsgBody struct {
Msg string
}
type Msg struct {
MsgHead
MsgBody
}
1 服务器端代码
package main
import (
"fmt"
"net"
"os"
"protocol"
rlp "github.com/ethereum/go-ethereum/rlp"
)
func main(){
service := "127.0.0.1:8080"
listener , err := net.Listen("tcp", service)
if err != nil {
fmt.Println(err)
}
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println(err)
}
//
strmsg := "asked: Hello world"
var msg protocol.Msg
msg.MsgHead.Len = 32
msg.MsgBody.Msg = strmsg
buf, err := rlp.EncodeToBytes(msg)
if err != nil {
fmt.Println(err)
os.Exit(0)
}
_, err = conn.Write(buf)
if err != nil {
fmt.Println(err)
}
}
}
2 客户端代码
package main
import (
"fmt"
"net"
"protocol"
rlp "github.com/ethereum/go-ethereum/rlp"
)
func main(){
service := "127.0.0.1:8080"
conn, err := net.Dial("tcp", service)
defer conn.Close()
if err != nil {
fmt.Println(err)
}
c := make([]byte,1024)
nbytes, err:= conn.Read(c)
if err != nil {
fmt.Println(err)
}
M := c[:nbytes]
T := protocol.Msg{}
err = rlp.DecodeBytes(M, &T)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%d,%s\n", T.Len,T.Msg)
}
3 知识
RLP (递归长度前缀)提供了一种适用于任意二进制数据数组的编码,RLP已经成为以太坊中对对象进行序列化的主要编码方式。RLP的唯一目标就是解决结构体的编码问题;对原子数据类型(比如,字符串,整数型,浮点型)的编码则交给更高层的协议;以太坊中要求数字必须是一个大端字节序的、没有零占位的存储的格式(也就是说,一个整数0和一个空数组是等同的)。
/*
rlp包用法
rlp目的是可以将常用的数据结构,uint,string,[]byte,struct,slice,array,big.int等序列化以及反序列化.
要注意的是rlp特别不支持有符号数的序列化
具体用法见下
*/
//编码
type TestRlpStruct struct {
A uint
B string
C []byte
BigInt *big.Int
}
//rlp用法
func TestRlp(t *testing.T) {
//1.将一个整数数组序列化
arrdata, err := rlp.EncodeToBytes([]uint{32, 28})
fmt.Printf("unuse err:%v\n", err)
//fmt.Sprintf("data=%s,err=%v", hex.EncodeToString(arrdata), err)
//2.将数组反序列化
var intarray []uint
err = rlp.DecodeBytes(arrdata, &intarray)
//intarray 应为{32,28}
fmt.Printf("intarray=%v\n", intarray)
//3.将一个布尔变量序列化到一个writer中
writer := new(bytes.Buffer)
err = rlp.Encode(writer, true)
//fmt.Sprintf("data=%s,err=%v",hex.EncodeToString(writer.Bytes()),err)
//4.将一个布尔变量反序列化
var b bool
err = rlp.DecodeBytes(writer.Bytes(), &b)
//b:true
fmt.Printf("b=%v\n", b)
//5.将任意一个struct序列化
//将一个struct序列化到reader中
_, r, err := rlp.EncodeToReader(TestRlpStruct{3, "44", []byte{0x12, 0x32}, big.NewInt(32)})
var teststruct TestRlpStruct
err = rlp.Decode(r, &teststruct)
//{A:0x3, B:"44", C:[]uint8{0x12, 0x32}, BigInt:32}
fmt.Printf("teststruct=%#v\n", teststruct)
}