Skip to content

Commit cb78d11

Browse files
author
hero
committed
设计 id + data 的ws 协议
1 parent 7872499 commit cb78d11

File tree

7 files changed

+462
-216
lines changed

7 files changed

+462
-216
lines changed

websocket/msg.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package gateway
2+
3+
import (
4+
"encoding/binary"
5+
"errors"
6+
"github.com/golang/protobuf/proto"
7+
"math"
8+
"reflect"
9+
)
10+
11+
var (
12+
ErrMsgNotProto = errors.New("msg not proto")
13+
ErrProtocol = errors.New("protocol too much")
14+
ErrNotRegister = errors.New("protocol not register")
15+
ErrMsgShort = errors.New("msg too short")
16+
)
17+
18+
var mgPrt *MsgProtocol
19+
20+
//协议
21+
// id + proto.Message
22+
type MsgProtocol struct {
23+
msgID map[reflect.Type]uint16
24+
msgInfo map[uint16]reflect.Type
25+
useBigEndian bool
26+
}
27+
28+
func NewMsgProtocol(useBigEndian bool) {
29+
mgPrt = &MsgProtocol{
30+
msgID: make(map[reflect.Type]uint16),
31+
msgInfo: make(map[uint16]reflect.Type),
32+
useBigEndian: useBigEndian,
33+
}
34+
}
35+
36+
func GetMsgProtocol() *MsgProtocol {
37+
if mgPrt == nil {
38+
panic("msg prt nil")
39+
}
40+
return mgPrt
41+
}
42+
43+
func (m *MsgProtocol) Register(msg proto.Message, eventType uint16) error {
44+
msgType := reflect.TypeOf(msg)
45+
if msgType == nil || msgType.Kind() != reflect.Ptr {
46+
return ErrMsgNotProto
47+
}
48+
if len(m.msgInfo) >= math.MaxUint16 {
49+
return ErrProtocol
50+
}
51+
m.msgInfo[eventType] = msgType
52+
m.msgID[msgType] = eventType
53+
return nil
54+
}
55+
56+
func (m *MsgProtocol) Marshal(msg interface{}) ([]byte, error) {
57+
msgType := reflect.TypeOf(msg)
58+
event, ok := m.msgID[msgType]
59+
if !ok {
60+
return nil, ErrNotRegister
61+
}
62+
data, err := proto.Marshal(msg.(proto.Message))
63+
if err != nil {
64+
return nil, err
65+
}
66+
var (
67+
id = make([]byte, 2)
68+
ptrData = make([]byte, 2+len(data))
69+
)
70+
if m.useBigEndian {
71+
binary.BigEndian.PutUint16(id, event)
72+
} else {
73+
binary.LittleEndian.PutUint16(id, event)
74+
}
75+
copy(ptrData[:2], id)
76+
copy(ptrData[2:], data)
77+
return ptrData, nil
78+
}
79+
80+
func (m *MsgProtocol) Unmarshal(msg []byte) (interface{}, error) {
81+
if len(msg) < 2 {
82+
return nil, ErrMsgShort
83+
}
84+
var id uint16
85+
if m.useBigEndian {
86+
id = binary.BigEndian.Uint16(msg[:2])
87+
} else {
88+
id = binary.LittleEndian.Uint16(msg[:2])
89+
}
90+
msgType, ok := m.msgInfo[id]
91+
if !ok {
92+
return nil, ErrNotRegister
93+
}
94+
var data = reflect.New(msgType.Elem()).Interface()
95+
err := proto.Unmarshal(msg[2:], data.(proto.Message))
96+
if err != nil {
97+
return nil, err
98+
}
99+
return data, nil
100+
}

websocket/msg.pb.go

Lines changed: 183 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

websocket/msg.proto

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
syntax = "proto3";
2+
package gateway;
3+
//错误码
4+
enum STATUS {
5+
//1~99, 通用错误码
6+
SUCCESS = 0;
7+
UNKNOWN_ERROR = 2; // 未知错误
8+
}
9+
// id 小于20的为保留协议 业务协议不能占用
10+
//id = 1
11+
message Ping{
12+
int64 Times = 1;
13+
}
14+
15+
//id = 2
16+
message Pong{
17+
int64 Times = 1;
18+
}
19+
20+
//id = 3 通用错误协议
21+
message ErrorEx {
22+
STATUS status = 1;
23+
string Msg = 2;
24+
int64 Times = 3;
25+
}

websocket/msg_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package gateway
2+
3+
import (
4+
"os"
5+
"testing"
6+
)
7+
8+
func TestMain(m *testing.M) {
9+
NewMsgProtocol(true)
10+
os.Exit(m.Run())
11+
}
12+
13+
func TestNewMsgProtocol(t *testing.T) {
14+
p := GetMsgProtocol()
15+
err := p.Register(&Ping{}, 1)
16+
if err != nil {
17+
t.Error(err)
18+
}
19+
data, err := p.Marshal(&Ping{Times: 1})
20+
if err != nil {
21+
t.Error(err)
22+
}
23+
info, err := p.Unmarshal(data)
24+
if err != nil {
25+
t.Error(err)
26+
}
27+
t.Log(info.(*Ping))
28+
}

0 commit comments

Comments
 (0)